C 如何使用带有信号的叉子?

C 如何使用带有信号的叉子?,c,signals,fork,C,Signals,Fork,我不确定是否还有更复杂的信号和问题。孩子或家长的信号呼叫有区别吗 当一个子对象被分叉时,它现在是父对象,而只是前一个父对象的子对象吗 由于包含处理程序,默认处理程序是否无效。那么,您能否将SIGINT更改为不终止进程 int count = 0; void killhandler(int sig){ printf("SIGKILL received\n"); return; } void childhandler(int sig){ int status; w

我不确定是否还有更复杂的信号和问题。孩子或家长的信号呼叫有区别吗

当一个子对象被分叉时,它现在是父对象,而只是前一个父对象的子对象吗

由于包含处理程序,默认处理程序是否无效。那么,您能否将
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);
}
int count=0;
无效killhandler(int-sig){
printf(“收到SIGKILL\n”);
返回;
}
void childhandler(int-sig){
智力状态;
等待(&状态);
计数+=WEXITSTATUS(状态);
返回;
}
main(){
int i;//for循环迭代器
pid_t pid[3];//子进程的pid
信号(SIGKILL,killhandler);
信号(SIGCHLD,childhandler);
//Fork 3子进程

对于(i=0;i当子进程分叉时,它非常接近父进程的精确副本。对于单线程进程,有三个关键区别:

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

    不能将信号处理程序设置为捕获SIGKILL。该信号永远不会被捕获

    孩子或家长的信号呼叫有区别吗

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

    当一个子对象被分叉时,它现在是父对象,而只是前一个父对象的子对象吗

    它肯定是父母的孩子。它是否成为父母取决于它是否为自己的孩子分叉

    由于包含处理程序,默认处理程序是否无效。因此,能否将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);
    }
    
    SIGINT的默认处置是终止进程,但您可以捕获并处理SIGINT,也可以阻止或忽略它。默认处置与其说是无效的,不如说是重写的,直到(如果)您再次更改它

    为什么从未打印“收到SIGKILL”

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

    在您的程序中,您试图将SIGKILL设置为其默认值,事实上,它是子系统中唯一的配置。由于您的子系统立即退出,来自父系统的信号可能永远不会被传递,因为子系统已经死亡,并且父系统中的
    kill
    可能因ESRCH而失败,例如,没有具有该pid的子系统存在任何lo一个
    sleep
    在那里会很有帮助,这样他们就可以活得足够长以至于被杀。(我喜欢这个术语。)

    您使用的
    WEXITSTATUS
    是错误的。如果您的目的是统计自愿退出而不是被杀的孩子的数量,那么您可能只需要使用WIFEXITED或WIFSIGNALED的简单计数器。WEXITSTATUS返回自己退出的孩子的状态代码。它可以是0、1、50或75。添加它就可以了o变量可能不是您想要的

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