【问题标题】:Lost signals from child to parent从孩子到父母的丢失信号
【发布时间】:2019-04-12 15:01:05
【问题描述】:

我正在创建几个子进程,它们向它们的父进程发送信号并死掉。我只是数了数。但我从来没有得到正确的计数。有些信号永远不会被处理程序捕获。

我应该如何编码?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> 
#include <sys/wait.h>

int ended = 0;

void handler(int sig){
    ended++;
}

int main(int argc, char **argv){
    int i;
    pid_t pid, ppid;

    if (signal(SIGUSR1, handler) < 0) {
        fprintf(stderr, "signal failed.\n");
        exit (-1);
    }

    ppid = getpid();

    for (i = 0; i < 50; i++){
        if ((pid = fork()) < 0){
            fprintf(stderr, "fork failed.\n");
            exit(-1);
        }
        if (pid == 0){  
            kill(ppid, SIGUSR1);
            exit(0);
        }       
    }

    while (wait(NULL) > 0);

    printf("ended = %d\n", ended);

    return 0;
} 

这个程序的输出有时是 47,有时是 39……但从来不是 50

【问题讨论】:

  • 如果多个信号同时出现(下一个在前一个处理之前),只会触发一个信号。未决信号是一种状态而不是计数。
  • 除了 Zang 的注释之外,您不能在通过 kill 调用的信号处理程序内写入静态 int,这是未定义的行为。见en.cppreference.com/w/c/program/signal

标签: c linux


【解决方案1】:

这里的问题是信号充当硬件中断,而您的处理函数将是 ISR(中断服务例程)。然后,如果多个相同值的信号“同时”发生,Linux 内核将它们视为只有一个信号。信号并非设计为以这种方式使用。一个信号应该用于将一个进程的状态通知给另一个进程。要实现进程之间的通信,您应该使用 IPC(进程间通信)机制,例如队列、套接字或管道。

【讨论】:

    【解决方案2】:

    谢谢,

    我发现问题可以使用实时信号来解决。只需用 SIGRTMIN 更改 SIGUSR1。实时信号已排队 (http://man7.org/linux/man-pages/man7/signal.7.html)。

    此解决方案是否有任何负面影响?

    【讨论】:

      【解决方案3】:

      它正在工作..

      #include <stdlib.h>
      #include <unistd.h>
      #include <sys/wait.h>
      
      int ended = 0;
      
      void handler(int sig)
      {
          ended++;
      }
      
          int main(int argc, char **argv)
          {
              int i;
              pid_t pid, ppid;
      
              if (signal(SIGUSR1, handler) < 0)
              {
                  fprintf(stderr, "signal failed.\n");
                  exit (-1);
              }
      
              ppid = getpid();
      
              for (i = 0; i < 50; i++)
              {
                  if ((pid = fork()) < 0)
                  {
                      fprintf(stderr, "fork failed.\n");
                      exit(-1);
                  }
                  if (pid == 0)
                  {
                      kill(ppid, SIGUSR1);
                      exit(0);
                  }
              }
      
              while (wait(NULL) > 0);
      
              printf("ended = %d\n", ended);
      
              return 0;
          }
      

      【讨论】:

      • 这是相同的代码,只是无缘无故地重新格式化了吗?
      猜你喜欢
      • 2015-09-14
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 2019-11-24
      • 2021-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多