C 为什么我只给fork打过一次电话却收到不止一个信号?

C 为什么我只给fork打过一次电话却收到不止一个信号?,c,linux,process,signals,C,Linux,Process,Signals,我正在研究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

我正在研究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;
}
#包括
#包括
#包括
#包括
#包括
#包括
void filsFini(内部信号){
printf(“子项已完成\n”);
}
int main(){
pid_t pid;
系统(“清除”);
如果((pid=fork())==0){
printf(“处于中断状态的孩子”);
对于(;);
}
printf(“父%d\n”,getpid());
系统(“ps-lH”);
(无效)信号(SIGCHLD、filsFini);
printf(“点击按钮结束\n”);
getchar();
kill(pid,SIGINT);
系统(“ps-lH”);
waitpid(pid,NULL,0);
系统(“ps-lH”);
返回退出成功;
}

最后我得到了这个结果,我有一个问题是
printf(“Child finished\n”)编写了两次如何避免这种情况?

每次调用
系统(“ps-lH”)
都会创建额外的子级,并且还会收到
SIGCHLD
通知。不幸的是,没有任何方法可以控制您接收的子进程的通知。要么全力以赴,要么一事无成

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

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

  • system(“ps-lH”);
    也将调用
    fork()
    ,请参阅

  • 如果只想调用
    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;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    无效句柄_SIGINT(int sig){
    printf(“子项已完成\n”);
    退出(退出失败);
    }
    int main(){
    信号(SIGINT,句柄\ SIGINT);
    pid_t pid;
    如果((pid=fork())==0){
    printf(“处于中断状态的孩子”);
    对于(;;)
    ;
    }
    printf(“父%d\n”,getpid());
    系统(“ps-lH”);
    printf(“点击按钮结束\n”);
    getchar();
    kill(pid,SIGINT);
    printf(“\n等待前:\n”);
    系统(“ps-lH”);
    waitpid(pid,NULL,0);
    printf(“\n在waitpid之后:\n”);
    系统(“ps-lH”);
    返回退出成功;
    }
    
    我没有看到任何打印子进程的代码完成…也许您有其他版本?我在函数filsFini中用作信号SIGCHLDOK的处理程序,因此任务是检查只有子进程处理信号调用一次。也许您可以在filsFini中使用静态变量,最初为0。在第一次调用之后增加1,那么下次打电话就不打印了?也许吧但是我想知道为什么打两次电话因为孩子变成了僵尸一旦孩子死了它就会给父亲发一个信号所以只能打一次电话我想原因是waitpid,但我看不到yetOkay谢谢你有办法吗我只在发送信号Kill?@AbdoRabah Put
    printf(“Child finished\n”)
    之后,在
    main
    中的
    waitpid
    中打印了一次«Child finished»。非常感谢您的帮助