我的代码是一个简单的c代码,其中有两个进程,一个是父进程,一个是父进程,然后打印出它发送的信号;另一个进程是接收信号并打印接收到的进程的子进程,我的代码的输出是父进程:发送SIGHUP父进程:发送SIGINT父进程:发送SIGQUIT进程为父进程:发送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");
      
    }发布于 2021-12-22 11:59:45
代码的逻辑有几个“问题”(除了使用非异步信号安全函数)。
fork()之后开始工作。这取决于内核和系统。Linux内核允许您通过在/proc/sys/kernel/sched_child_runs_first中设置一个值来使其具有确定性,其中如果值为0(默认值)父程序首先运行,如果值为非零,则子程序首先运行。然而,依赖这个开关进行同步并不是一个好的做法,因为在多处理器环境中,如果我们有可用的,两者可以同时运行。
为了解决问题并保证执行顺序,您需要创建一个同步屏障。下面是基于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);
}发布于 2021-12-20 11:13:22
可能第一个信号是在子程序初始化其信号处理之前发送的。至少我可以通过在sleep(2);后面直接添加if (pid == 0) {来再现这种行为。
在开始发送信号之前,尝试在父进程中添加一个sleep()。
https://stackoverflow.com/questions/70420842
复制相似问题