【问题标题】:SIGINT ignored by multiple processesSIGINT 被多个进程忽略
【发布时间】:2015-05-09 20:56:27
【问题描述】:

我想创建三个进程,它们会打印一些东西,直到我按下 ctrl+c。您可以在下面看到我的尝试,但是当尝试停止程序时没有任何反应。当唯一的一个孩子被分叉时,它工作得很好。哪里可能有问题?提前致谢。

     void my_handler(int s){
          printf("Caught signal %d, I am dying\n",s);
       exit(1);
     }

     void doChild(int count){
     fprintf(stdout,"Child %d with pid: %d\n",count, getpid());
    }


     int main(int argc, char **argv){

     int count = 0;
     pid_t pid;
     struct sigaction sigIntHandler;
     sigIntHandler.sa_handler = my_handler;
     sigemptyset(&sigIntHandler.sa_mask);
     sigIntHandler.sa_flags = 0;
     sigaction(SIGINT, &sigIntHandler, NULL);
     fprintf(stdout, "Ahoj svjete!\n");

     for(;count < 3;count++){
            pid = fork();
    switch(pid){
             case -1:
                    perror("Fork :(");
                     exit(EXIT_FAILURE);

             case 0:
                     while(1){
                            doChild(count);
                    }
       }
    }

     exit(EXIT_SUCCESS);
    }

【问题讨论】:

  • main() 的参数,'argc' 和 'argv' 没有被使用。编译器将为每个未使用的参数发出警告。建议 1) 在启用所有警告的情况下编译,修复这些警告。对于上述一对警告,建议 'int main( void );
  • 检查'fork()'返回的值只检查最后一次fork调用,而不是之前的调用。建议将 pid 值的检查移到“for”循环内。
  • 使用制表符进行缩进,正如您在发布的代码中看到的那样,是一个非常糟糕的主意。为了我们人类读者,建议一致缩进。建议在每个左大括号 '{' 后缩进 4 个空格,在每个右大括号 '}' 之前不缩进
  • 首先,它只是代码的一部分...我要写一些getopt之类的东西:)其次,你说得对,我没有意识到这一点。

标签: c linux signals fork signal-handling


【解决方案1】:

正如 REACHUS 所指出的,您得到 8 个进程,而不是 3 个。此外,交换机在每个进程中测试 last fork calll 的结果,因此其中 4 个进程立即退出,而其他 4 个继续在doChild 循环中运行。

现在因为顶级进程(进行第一次分叉的初始进程)是其中一个退出的进程(它的fork 调用都返回子进程的 pid,从不为 0),shell 再次接管,这意味着当你点击 ctrl-C 时,它会进入 shell 而不是你的 fork 孩子。这些孩子永远不会看到 SIGINT(除非您使用 kill 明确将其发送给他们),所以永远不要退出。

【讨论】:

    【解决方案2】:

    在这个循环中:

    for(;count < 3;count++){
        pid = fork();
    }
    

    您将创建总共 8 个进程,因为您正在执行 fork() 3 次,即 1. 调用 fork() 给您 1*2=2 个进程,第二次调用 @ 987654327@ 为您提供 2*2=4 个进程,第三次调用 fork() 为您提供 4*2=8 个进程。

    此外,您设置信号处理程序的方式会将您的信号发送到整个process group(例如父母和孩子)。如果这不是您想要的,您应该查看setpgid()setsid() 函数,以使信号为每个子进程单独工作。

    编辑:

    这里是您的代码的修改版本,我添加了一些内容,可以帮助您了解正在发生的事情。您还可以在 Chris Dodds 的回答中找到有关代码中发生的情况的更多解释。发送信号现在将杀死所有子进程和父进程,但这段代码只是一个示例,让您了解它是如何工作的(正如我所说,您应该在这里使用进程组)。

    void my_handler(int s){
        printf("Caught signal %d, I am dying, my PID=%d\n",s, (int)getpid());
        exit(1);
    }
    
    void doChild(int count){
        fprintf(stdout,"Child %d with pid: %d\n",count, getpid());
    }
    
    int main(int argc, char **argv){
        int count = 0;
        int status;
        pid_t pid;
    
        for(;count < 2;count++){
            pid = fork();
        }
    
        printf("My PID=%d\n", (int)getpid());
        fprintf(stdout, "Ahoj svjete!\n");
    
        switch(pid){
            case -1:
                perror("Fork :(");
                exit(EXIT_FAILURE);
            case 0:
                signal(SIGINT, my_handler);
                while(1){
                    doChild(count);
                }
            default:
                printf("Parent\n");
                sigignore(SIGINT);
                wait(&status);
        }
    
        printf("Process %d ended life.\n", (int)getpid());
        exit(EXIT_SUCCESS);
    }
    

    【讨论】:

    • 我修复了进程数量的问题...但是信号处理仍然不起作用。
    猜你喜欢
    • 2012-10-08
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    相关资源
    最近更新 更多