簡體   English   中英

我想知道這個程序的 output 背后的原因

[英]i want to know the reason behind the output of this program

在原始程序中 kill(pid, SIGUSR1); 首先調用 pause(); 在父進程中和在子進程中 pause(); 先調用后調用 kill(getppid(), SIGUSR1); 其 output 如下所示

如果我替換 kill(getppid(), SIGUSR1); 在更改的程序中暫停(); 在子進程中 output 完全不同我已將 output 粘貼在代碼下方。

有人能解釋一下為什么 output 會改變嗎

**********************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


如果一個進程在為其設置信號處理程序之前接收到 SIGUSR1(並且沒有忽略或持有它),則該進程將被終止。 (有關詳細信息。請參閱信號手冊頁)。

您的代碼(兩個版本)有幾個競爭條件。

在第一個版本中:

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 設置信號處理程序,事情會更好。 這樣,父母和孩子都准備好處理信號。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM