【问题标题】:i want to know the reason behind the output of this program我想知道这个程序输出背后的原因
【发布时间】:2021-03-11 23:29:59
【问题描述】:

在原始程序中 kill(pid, SIGUSR1);首先调用 pause();在父进程中和在子进程中 pause();先调用后调用 kill(getppid(), SIGUSR1);它的输出如下所示

如果我替换 kill(getppid(), SIGUSR1); 在更改的程序中暂停();子进程中的输出完全不同,我将输出粘贴在代码下方。

谁能解释一下为什么输出会改变

**********************ORIGINAL PROGRAM***********************************
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void action(int dummy){  
     sleep(1); 
     printf("Switching\n");
}

int main(int argc, char *argv[]){  
    pid_t pid;

    if((pid=fork())>0){//parent  
        sleep(1);
        while(1){
            printf("Parent is running\n");  
            kill(pid, SIGUSR1);  
            signal(SIGUSR1, action);  
            pause();
        }
    }
    else  //child code
        while(1){//child  
            signal(SIGUSR1, action);  
            pause();
            printf("Child is running\n");  
            kill(getppid(), SIGUSR1);
    }
}


//OUTPUT OF THIS PROGRAM
Parent is running
Switching
Child is running
Switching
Parent is running
Switching
Child is running
Switching
Parent is running
Switching
Child is running
Switching
Parent is running
Switching
Child is running
Switching
Parent is running
Switching
Child is running






*********************CHANGED PROGRAM************************

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void action(int dummy){  
     sleep(1); 
     printf("Switching\n");
}

int main(int argc, char *argv[]){  
    pid_t pid;

    if((pid=fork())>0){//parent  
        sleep(1);
        while(1){
            printf("Parent is running\n");  
            kill(pid, SIGUSR1);  
            signal(SIGUSR1, action);  
            pause();
        }
    }
    else  //child code
        while(1){//child  
            signal(SIGUSR1, action);  
            kill(getppid(), SIGUSR1);
            printf("Child is running\n");  
             pause();
    }
}





//OUTPUT OF THIS PROGRAM
//Child is running
//User defined signal 1


【问题讨论】:

    标签: c signals computer-science kill-process pause


    【解决方案1】:

    如果一个进程在为其设置信号处理程序之前收到 SIGUSR1(并且没有忽略或持有它),则该进程将被终止。 (详情见信号man page)。

    您的代码(两个版本)有几个竞争条件。

    在第一个版本中:

    if((pid=fork())>0){//parent  
        sleep(1);
        while(1){
            printf("Parent is running\n");  
            kill(pid, SIGUSR1);  
            signal(SIGUSR1, action);  
            pause();
        }
    }
    else  //child code
        while(1){//child  
            signal(SIGUSR1, action);  
            pause();
            printf("Child is running\n");  
            kill(getppid(), SIGUSR1);
    }
    

    孩子将等待 SIGUSR1。

    大约在同一时间,父母会睡觉,然后向孩子发送 SIGUSR1。

    孩子收到信号后,会做几个 printfs,然后发送 SIGUSR1 给父母。

    大约在同一时间,父级将为 SIGUSR1 设置一个信号处理程序。

    很可能(但不一定总是如此)孩子会在父母执行 sleep(1) 时设置信号处理程序;从父母发送给孩子的信号将被捕获而不是导致孩子被终止。

    很可能(但不一定总是如此)当子进程完成它的两个 printfs 时,父进程已经设置了信号处理程序;从孩子发送给父母的信号将被捕获而不是导致父母被终止。

    但是,由于存在竞争条件,时间上的微小变化可能会导致事情中断。

    在第二个版本中:

    if((pid=fork())>0){//parent  
        sleep(1);
        while(1){
            printf("Parent is running\n");  
            kill(pid, SIGUSR1);  
            signal(SIGUSR1, action);  
            pause();
        }
    }
    else  //child code
        while(1){//child  
            signal(SIGUSR1, action);  
            kill(getppid(), SIGUSR1);
            printf("Child is running\n");  
            pause();
    }
    

    子进程在它分叉后立即将 SIGUSR1 发送给父进程,这几乎肯定会在父进程处于 sleep(1) 中间时发生。由于父级尚未为 SIGUSR1 设置处理程序,因此信号将终止它。然后 shell 打印出 用户定义的信号 1,这是 SIGUSR1 信号的长名称。

    如果您在分叉之前为 SIGUSR1 设置信号处理程序,事情会更好。这样,父母和孩子都会准备好处理信号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-28
      • 2022-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-20
      相关资源
      最近更新 更多