为啥我无法捕捉到父母发送的孩子的信号?

Posted

技术标签:

【中文标题】为啥我无法捕捉到父母发送的孩子的信号?【英文标题】:Why I can't catch the signal in the child which is sent by parent?为什么我无法捕捉到父母发送的孩子的信号? 【发布时间】:2019-01-19 15:40:46 【问题描述】:

我刚刚学习了 C 中的信号,我想从父级向子级发送信号,但我不明白为什么处理程序在这里不起作用...

我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>

void handler(int signumber)
  printf("Signal with number %i has arrived\n",signumber);


int main()

  sigset_t sigset;
  sigemptyset(&sigset); //empty signal set
  sigaddset(&sigset,SIGTERM); //SIGTERM is in set
  //sigfillset(&sigset); //each signal is in the set
  sigprocmask(SIG_BLOCK,&sigset,NULL); //signals in sigset will be blockedhere

  signal(SIGTERM,handler); //signal and handler is connetcted

  pid_t child=fork();
  if (child>0)
  
    printf("I'm parrent\n");
    printf("Waits 2 seconds, then send a SIGTERM %i signal (it is blocked)\n",SIGTERM);
    sleep(2);
    kill(getppid(),SIGTERM); 
    printf("I sent it.\n");   
  
  else
  
    wait(NULL);
    sleep(2);
    printf("I'm the child wainting for signal.\n");

    sigprocmask(SIG_UNBLOCK,&sigset,NULL); 


    int status;
    wait(&status);
    printf("Child process ended\n");
  
  return 0;

结果如下:

I'm parrent
Waits 2 seconds, then send a SIGTERM 15 signal (it is blocked)
I'm the child wainting for signal.
Child process ended
I sent it.

还有一件事,我知道,我必须使用sigsuspend(sigset); 而不是处理程序,因为printf isn't safe in handler,但是在这种情况下我该如何使用它呢?

【问题讨论】:

您的孩子正在呼叫wait...您认为它在等待什么进程?父级正在向其父级发送信号....为什么您认为它会传递给子级? @WilliamPursell 好吧,我想从父母那里发送给孩子,所以我想,wait 孩子可以等待父母...... @Gábor wait 在 UNIX 语言中表示检索进程更改/终止状态。 UNIX 只允许父母检索他们孩子的进程更改状态,而不是相反。 @PSkocik 好的,谢谢,我想,我明白了。 【参考方案1】:

Wait主要是为了收获child status(一般是为了观察child status的变化)。 在孩子身上使用它没有多大意义。 是的,您可以使用sigsuspend 等待信号。 它可能看起来像这样:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>


#define WRITE(Str) (void)write(1,Str,strlen(Str))
void handler(int signumber)

    WRITE("Signal arrived\n");


int main()

  sigset_t sigset;
  sigemptyset(&sigset); //empty signal set
  sigaddset(&sigset,SIGTERM); //SIGTERM is in set
  sigprocmask(SIG_BLOCK,&sigset,NULL); //signals in sigset will be blockedhere

  signal(SIGTERM,handler); //signal and handler is connetcted

  pid_t child=fork();
  if(0>child) return EXIT_FAILURE;
  if (child>0) 
    int status;
    printf("I'm the parent\n");
    printf("Waits 2 seconds, then send a SIGTERM %i signal (it is blocked)\n",SIGTERM);
    sleep(2);
    kill(child,SIGTERM);
    printf("I sent it.\n");
  
  else
  
    sigemptyset(&sigset); //the child has a different addr-space
                          //so this won't affect the parent
    printf("I'm the child waiting for signal.\n");
    sigsuspend(&sigset);
    printf("Child process ended\n");

  
  return 0;

有关详细信息,请参阅各个系统功能的手册页。您也应该检查返回码,即使这些特定函数中的大多数通常不会失败,除非您将它们称为错误(但有些确实如此,例如,如果您的内存不足,fork() 可能会非常实际地失败)。

【讨论】:

非常感谢!如果我认为kill(child,SIGTERM); 将父母指向孩子,我错了吗? 如果我有多个孩子,我该如何选择哪一个?我可以选择吗? @Gábor 这就是第一个参数的用途。阅读手册。 linux.die.net/man/2/kill 如何同时使用信号和管道?我试过了,他们分开工作,但如果我想在一个程序中使用它们而不是他们,不想工作。我在这里写的:***.com/questions/54394374/…

以上是关于为啥我无法捕捉到父母发送的孩子的信号?的主要内容,如果未能解决你的问题,请参考以下文章

Linux信号:孩子没有收到

如何让子进程等待信号?

C POSIX子级根据文件内容发送信号,父级将接收到的信号与文件匹配

父子信号的waitpid

有没有办法通过信号发送值

无法从 QtGui.QStandardItem 发出信号