父母在父母创造信号后使用信号杀死n个孩子

我试图从父进程创建n个子进程,然后在创建n个子进程之后,父进程必须使用信号一一杀死它们。当他杀死每个孩子时,他必须等待2秒才能杀死下一个孩子。最后,当他杀死所有孩子时,他也必须完成比赛。每个子级在创建时都必须打印其进程ID,直到父级将其杀死为止。我尝试结合从各个网站上读取的内容,到目前为止,我能够创建子代并打印其进程ID,但无法使用信号杀死它们。我怎么做?

这是代码:

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

void handle_sigint(int sig) { 
    signal(sig,handle_sigint);
    exit(0);
} 

int main(int argc, char *argv[]) {
    char *ptr=argv[1];
    int n=atoi(ptr);//number of processes to be created
    pid_t p[n];

    for(int i = 0; i < n; i++) {  
        signal(SIGINT, handle_sigint);    
        if ((p[i] = fork()) == 0) {
            while(1) 
                printf("%d %d\n",getpid(),i);                   
        } 
        sleep(2);                                
    }

    for (int i = 0; i < n; i++) {
        kill(p[i],SIGINT);
        sleep(2);
    }

    for (int i = 0; i < n; i++) {
        wait(NULL);
    }

    return 0;
}
评论
  • ofbgg
    ofbgg 回复

    在输出pid和id之后,您应该等待来自父进程的信号。

    diff --git a/foo.c b/foo.c
    index aefb62f..902c6a3 100644
    --- a/foo.c
    +++ b/foo.c
    @@ -3,6 +3,7 @@
     #include <sys/types.h>
     #include <unistd.h>
     #include <signal.h>
    +#include <sys/wait.h>
     void handle_sigint() 
     { 
         exit(0);
    @@ -17,14 +18,15 @@ int main(int argc, char *argv[])
    
         for(int i = 0;i<n;i++)
         {      
    -        if(p[i]=fork()==0)
    +        if((p[i]=fork())==0)
             {
                  signal(SIGINT, handle_sigint);
    
    -            while(1) 
                     printf("%d %d\n",getpid(),i);
    +            pause(); // Wait signal.
    
             }                                 
    +        sleep(1); // Avoid resource race.
         }
    
         for(int i=0;i<n;i++)
    
  • 敌敌畏
    敌敌畏 回复

    In the first place, you don't need a signal handler, because there are many signals whose default action is to cause the receiving process to terminate. The SIGINT you're already using is one of those, in fact, but SIGTERM would be a more appropriate choice for the purpose. I would simplify by getting rid of the handler and its registration, and I would have the parent send SIGTERM instead of SIGINT.

    If you do retain the signal handler, though, then you should use sigaction(), not signal(), to register it, and you should omit the re-registration from the handler implementation, as proper use of sigaction() makes it unnecessary. Also, signal handlers are permitted to call only async-signal-safe functions, and exit() is not one of those. You could use _exit() or _Exit() instead, but again, it would be simpler to just drop the handler altogether.

    All that notwithstanding, however, I'm inclined to suspect that the reason the original code failed was the incorrect signature of the signal handler, which you corrected in your edit. It's still wrong for the handler to call exit(), but in practice, it is reasonably likely that the manifestation of the resulting undefined behavior includes the program terminating.