【问题标题】:Why do I get more than one SIGCHLD when I only called fork once?为什么我只调用一次 fork 会得到多个 SIGCHLD?
【发布时间】:2018-12-02 14:57:50
【问题描述】:

我正在研究 Linux 中的信号,并试图了解进程的机制。我写了这段代码:

#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

void filsFini(int sig){
  printf("The Child finished\n");
}

int main(){
  pid_t pid;
  system("clear");
  if((pid=fork())==0){
    printf("Child in a break\n");
    for(;;);
  }

  printf("The father %d \n",getpid());
  system("ps -lH");
  (void) signal(SIGCHLD,filsFini);
  printf("hit a button to end\n");
  getchar();
  kill(pid,SIGINT);
  system("ps -lH");
  waitpid(pid,NULL,0);
  system("ps -lH");
  return EXIT_SUCCESS;
}

最后我得到了这个结果,我有一个问题是printf("Child finished\n");被写了两次我怎样才能避免这种情况?

【问题讨论】:

  • 我没有看到任何打印 Child finished 的代码...也许你有另一个版本?
  • 它在函数 filsFini 中,我用作信号 SIGCHLD 的处理程序
  • OK,所以任务是检查只有子进程只处理一次信号调用。也许你可以在 filsFini 中使用一个静态变量,初始值为 0。第一次调用后加 1,那么下次调用不打印?
  • 也许..但我想知道它被调用两次的原因..因为孩子会变成僵尸,一旦孩子死了,它就会向父亲发送一个 SIGCHLD,所以它应该只被调用曾经..我认为 waitpid 是原因,但我还没有看到它

标签: c linux process signals


【解决方案1】:

每次调用system("ps -lH"),您都会创建更多的孩子,并且您也会收到SIGCHLD 的通知。不幸的是,没有任何方法可以控制您收到SIGCHLD 通知的哪些子进程。要么全有,要么全无。

对于您编写的程序,我建议您什么都不选:不要为SIGCHLD 安装处理程序。您可以依靠已有的waitpid 调用,在您直接创建的子进程完成时通知您。 system 将负责为它创建的子进程调用 waitpid;您不必担心它们。

(在编写需要等待子进程完成和异步 I/O 事件的可变组合的更复杂的程序时,SIGCHLD 的全有或全无本质是一个主要的麻烦,特别是如果涉及的库可能创建主事件循环不知道的子进程。但在你到达那里之前不要担心。)

【讨论】:

  • 好的,谢谢..您知道如何在发送信号 Kill 后仅打印一次 «孩子完成» 吗?
  • @AbdoRabah 将printf("Child finished\n") 放在waitpid 之后,在main 中。
【解决方案2】:
  1. system("ps -lH"); 也会调用fork(),请参阅http://man7.org/linux/man-pages/man3/system.3.html

  2. 如果你只想调用printf("Child finished\n");一次,你可以在子进程中捕获SIGINT并输出它。

以下code 可以工作:

#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>

void handle_SIGINT(int sig) {
  printf("The Child finished\n");
  exit(EXIT_FAILURE);
}

int main(){

  signal(SIGINT, handle_SIGINT);

  pid_t pid;
  if ((pid=fork()) == 0) {
    printf("Child in a break\n");
    for(;;)
      ;
  }

  printf("The father %d \n", getpid());
  system("ps -lH");
  printf("hit a button to end\n");
  getchar();
  kill(pid, SIGINT);
  printf("\nbefore waitpid:\n");
  system("ps -lH");
  waitpid(pid, NULL, 0);
  printf("\nafter waitpid:\n");
  system("ps -lH");

  return EXIT_SUCCESS;
}

【讨论】:

  • 非常感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-20
  • 2016-07-13
  • 2014-01-17
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
相关资源
最近更新 更多