簡體   English   中英

Linux 信號:孩子沒有收到

[英]Linux Signal : Child not receiving

我的代碼是一個簡單的 c 代碼,其中有兩個進程,第一個是父母發送信號並打印出它發送的內容,另一個是接收信號並打印它接收到的內容的子進程發送 SIGINT PARENT:發送 SIGQUIT 它應該是 PARENT:發送 SIGHUP 孩子收到 SIGHUP 等...

 // C program to implement sighup(), sigint()
    // and sigquit() signal functions
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>

    
    // function declaration
    void sighup(int);
    void sigint(int);
    void sigquit(int );
    void sigsegv(int );
    
    // driver code
    int main()
    {
      int pid;
    
      /* get child process */
      if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
      }
    
      if (pid == 0) { /* child */
        signal(SIGHUP, sighup);
        signal(SIGINT, sigint);
        signal(SIGQUIT, sigquit);
                    signal(SIGSEGV, sigsegv);
        for (;;)
          ; /* loop for ever */
      }
    
      else /* parent */
      { /* pid hold id of child */
        printf("\nPARENT: sending SIGHUP\n\n");
        kill(pid, SIGHUP);
    
        sleep(3); /* pause for 3 secs */
        printf("\nPARENT: sending SIGINT\n\n");
        kill(pid, SIGINT);
    
        sleep(3); /* pause for 3 secs */
        printf("\nPARENT: sending SIGQUIT\n\n");
        kill(pid, SIGQUIT);
        sleep(3);
      }
return  0 ;
    }
    
    // sighup() function definition
    void sighup(int signo)
    
    {
      signal(SIGHUP, sighup); /* reset signal */
      printf("CHILD: 1 [sighub]\n");
    }
    
    // sigint() function definition
    void sigint(int signo)
    
    {
      signal(SIGINT, sigint); /* reset signal */
      printf("CHILD: 2 [sigint]\n");
    }
    // sigsegv() function definition
    void sigsegv(int signo)
    
    {
      signal(SIGSEGV, sigsegv); /* reset signal */
      printf("CHILD: 11 [sigsegv]\n");
    }
    
    // sigquit() function definition
    void sigquit(int signo)
    {
    signal(SIGINT, sigquit); /* reset signal */
      printf("3 [sigquit]\n");
      
    }

可能在孩子初始化它的信號處理之前發送第一個信號。 至少我可以通過添加sleep(2); 直接在if (pid == 0) {之后。

在開始發送信號之前嘗試在父進程中添加sleep()

您對代碼的邏輯有幾個“問題”(除了使用非異步信號安全功能)。

  1. 不能保證哪個進程會在fork()之后開始工作。 這取決於 kernel 和系統。 Linux kernel 允許您通過在/proc/sys/kernel/sched_child_runs_first中設置一個值來使其具有確定性,其中如果值為 0(默認值),則父級首先運行,如果值為非零,則子級首先運行。 然而,依賴此開關進行同步並不是一個好習慣,因為在多處理器環境中,如果我們有可用的 CPU,兩者可以同時運行。

  2. 由於使用系統調用或由於 cpu 時間,進程可以在任何給定時刻被搶占。 因此,不能保證孩子在父母發出信號之前已經設置了所有的信號處理程序,所以一些信號會丟失(實際上在我的測試中,一旦睡眠被移除,我得到了所有信號都丟失的情況)。

  3. 出於與 2 相同的原因,不能保證孩子在父母發送新信號之前得到信號。

為了解決問題並保證執行順序,您需要創建一個同步屏障。 這是基於確保同步的 IPC 管道的示例。 在示例中,父母等待孩子設置信號,然后,對於它發送的每個信號,它都等待孩子確認信號已被接收。

// C program to implement sighup(), sigint()
// and sigquit() signal functions
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>


// function declaration
void sighup(int);
void sigint(int);
void sigquit(int );
void sigsegv(int );

int fd[2]; // communication pipe

// driver code
int main()
{
    int pid;

    if (pipe(fd)==-1)
    {
        fprintf(stderr, "Pipe Failed" );
        exit(1);
    }

    /* get child process */
    if ((pid = fork()) < 0) {
        perror("fork");
        exit(1);
    }

    if (pid == 0) { /* child */
        close(fd[0]); // Close reading end
        printf("Preparing the signals");
        signal(SIGHUP, sighup);
        printf(".");
        signal(SIGINT, sigint);
        printf(".");
        signal(SIGQUIT, sigquit);
        printf(".");
        signal(SIGSEGV, sigsegv);
        printf(".Signals ready\n");
        write(fd[1],"ready\0", 6);
        for (;;)
            ; /* loop for ever */
    }

    else /* parent */
    { /* pid hold id of child */
        char readb[1024];
        readb[1023] = 0; //Safty stop

        close(fd[1]); // Close writting end
        printf("Waiting for child to finish\n");
        read(fd[0], readb, 1023);
        printf("Child sends %s", readb);

        printf("\nPARENT: sending SIGHUP\n\n");
        kill(pid, SIGHUP);
        read(fd[0], readb, 1023);
        printf("%s\n", readb);

        printf("\nPARENT: sending SIGINT\n\n");
        kill(pid, SIGINT);
        read(fd[0], readb, 1023);
        printf("%s\n", readb);

        printf("\nPARENT: sending SIGQUIT\n\n");
        kill(pid, SIGQUIT);
        read(fd[0], readb, 1023);
        printf("%s\n", readb);

        close(fd[0]);
    }
    return  0 ;
}

// sighup() function definition
void sighup(int signo)
{
    signal(SIGHUP, sighup); /* reset signal */
    write(fd[1],"CHILD: 1 [sighub]\0",18);
}

// sigint() function definition
void sigint(int signo)

{
    signal(SIGINT, sigint); /* reset signal */
    write(fd[1],"CHILD: 2 [sigint]\0",18);
}
// sigsegv() function definition
void sigsegv(int signo)
{
    signal(SIGSEGV, sigsegv); /* reset signal */
    write(fd[1],"CHILD: 11 [sigsegv]\0",20);
}

// sigquit() function definition
void sigquit(int signo)
{
    signal(SIGINT, sigquit); /* reset signal */
    write(fd[1],"CHILD: 3 [sigquit]\0",19);
}

暫無
暫無

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

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