【问题标题】:How to use fork with signals?如何使用带有信号的叉子?
【发布时间】:2013-12-15 04:32:15
【问题描述】:

我不确定更复杂的信号和分叉问题。来自孩子或父母的信号呼叫之间有区别吗?

当一个孩子被分叉时,它现在是父母,但只是前父母的孩子吗?

由于包含处理程序,默认处理程序无效。那么您可以更改SIGINT 以不终止进程吗?

int count = 0;

void killhandler(int sig){
    printf("SIGKILL received\n");
    return;
}

void childhandler(int sig){
    int status;
    wait(&status);
    count += WEXITSTATUS(status);
    return;
}

main(){
    int i; // for loop iterator
    pid_t pid[3]; // pids of child processes
    Signal(SIGKILL, killhandler);
    Signal(SIGCHLD, childhandler);
    // Fork 3 child processes
    for(i=0; i<3; i++){
        pid[i] = fork();
        if(!pid[i]){ // If child process
            Signal(SIGKILL, SIG_DFL);
            exit(5);
        }
    }

    // Parent process only
    for(i=0; i<3; i++){
        kill(pid[i], SIGKILL);
    }
    sleep(5);
    printf("count = %d\n", count);

    exit(0);
}

为什么"SIGKILL received" 从未打印出来?

为什么计数只能是:0、5、10、15

【问题讨论】:

    标签: c signals fork


    【解决方案1】:

    来自孩子或父母的信号呼叫有区别吗?

    就它如何影响接收信号的进程而言,没有。

    当一个孩子被分叉时,它现在是父母,但只是前父母的孩子吗?

    它绝对是其父级的子级。它是否成为父母本身取决于它是否分叉自己的孩子。

    由于包含处理程序,默认处理程序无效。那么您可以更改 SIGINT 以不终止进程吗?

    SIGINT 的默认处置是终止进程,但您可以捕获和处理 SIGINT,或者您可以阻止或忽略它。在您再次更改之前(如果),默认配置与其说是被覆盖不如说是无效。

    为什么从来没有打印出“SIGKILL received”?

    您不能阻止、忽略或捕获 SIGKILL。你不会看到你的处理程序打印任何东西,因为它永远不会被 SIGKILL 调用。 SIGSTOP,同样不能被忽略、阻止或处理。这是这方面的两个特殊信号。

    在您的程序中,您正试图将 SIGKILL 设置为其默认值,实际上它在子级中的处置。由于您的孩子立即退出,因此可能永远不会传递来自父母的信号,因为孩子已经死了,并且父母中的 kill 可能会因 ESRCH 而失败,例如不再存在具有该 pid 的孩子。 sleep 在那里会很有帮助,这样他们就可以活得足够长而被杀死。 (一定会喜欢这个术语。)

    您对WEXITSTATUS 的使用是错误的。如果您的目的是计算自愿退出而不是被杀死的孩子的数量,您可能只需要一个使用 WIFEXITED 或 WIFSIGNALED 的简单计数器。 WEXITSTATUS 返回自行退出的子进程的状态代码。它可能是 0 或 1 或 50 或 75。将它添加到变量可能不是您想要的。

    信号是一个令人困惑的话题,因为洋葱有好几层,并且规则和平台特定语义有足够多的例外使它们令人沮丧。我从来没有找到一个可以详尽地涵盖它们的单一来源。也就是说,信号处理和处理程序是洋葱的外层,网络上有许多可用的资源很好地涵盖了这些。

    【讨论】:

      【解决方案2】:

      当子进程被派生时,它非常接近于父进程的精确副本。对于单线程进程,存在三个主要区别:

      1. 父进程ID不同
      2. 进程 ID 不同。
      3. fork()的返回值不同

      (有关其他差异,请参阅fork() 的 POSIX 手册页。)子级中的信号处理程序与父级相同。但是,孩子当然可以独立地更改其任何信号处理程序。

      您不能设置信号处理程序来捕获 SIGKILL。永远无法捕捉到这个信号。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-09-23
        • 1970-01-01
        • 1970-01-01
        • 2012-09-20
        • 2011-01-17
        • 2011-12-09
        • 2011-10-14
        相关资源
        最近更新 更多