进程A向进程B发送signalfd.B尝试read()时会发生什么?如果B将signalfd添加到epoll,epoll_wait何时返回?
答案 0 :(得分:1)
手册页中有一条线索:
通过unix socket传输的fork(2)语义
在fork(2)之后,子进程继承了signalfd文件描述符的副本。从子文件描述符中读取(2)将返回有关排队到子项的信号的信息。
signalfd
应该与fork()
继承的行为相同。基本上,哪个过程创建signalfd
无关紧要; read()
始终返回排队到调用read()
的进程的信号。
与epoll
存在奇怪的交互,但是:由于epoll
事件队列是在任何特定进程的上下文之外进行管理的,因此它根据所有进程决定signalfd
的准备情况。最初调用epoll_ctl()
以注册对signalfd
的兴趣的过程。因此,如果您安排使用signalfd
FD观看epoll
,然后将两个FD发送到另一个进程,则接收过程将看到不一致的结果:epoll
仅在发送时发出信号准备就绪process有一个信号,但signalfd
将返回接收过程的信号。
这种情况特别容易使用fork()
。例如,如果初始化事件循环库而不是使用epoll
和signalfd
,则调用fork()
(例如,为了守护进程),然后尝试在子进程中使用该库,你可能会发现你无法接收信号。 (我昨天花了一整天时间试图调试这样的问题。)
答案 1 :(得分:-1)
这是不一致的,或至少是一个记录不足的角落案例。仔细阅读 signal(7)。
进程A可以使用kill(2)或killpg(2)向进程B发送信号(而不是signalfd)。
进程B处理信号(并且有一些默认行为来处理某些信号)。它可以使用旧的signal(2)或更新的sigaction(2)安装(以POSIX标准方式)信号处理程序,或者可以使用signalfd(2)来获取(以Linux特定的方式)文件描述符上的一些数据。
因此,signalfd
为成功提供了一个新的文件描述符,例如open
或socket
。
阅读signalfd(2)
文档,它解释了B端读取时发生了什么(内核正在发送一些struct signalfd_siginfo
,我想从获取信号的过程的角度来看,而不是读取文件描述符的过程,请参阅内核的源文件fs/signalfd.c),或者在poll
给出的文件描述符上等待signalfd
或 epoll ;当B接收到信号时,轮询将成功。
成功的signalfd
只是获取打开的文件描述符(如文件描述符open
,socket
,accept
,{{1你给了你)并且你不会与不相关的进程共享那个文件描述符。
如果您敢于使用sendmsg(2)
套接字在unix(7)套接字上使用pipe
向其他进程发送该文件描述符,我将不会做出任何假设。我想它类似于pipe(7) - s或fifo(7) - s或netlink(7) - s。但我当然不会这样做:SCM_RIGHTS
是特定于Linux的,并且您处于无证件角落情况。阅读内核源代码以了解正在发生的事情,或在kernelnewbies上询问。并且不要指望未来的内核在未记录的方面与现有内核保持一致......