将 signalfd 发送到另一个进程
Posted
技术标签:
【中文标题】将 signalfd 发送到另一个进程【英文标题】:Sending signalfd to another process 【发布时间】:2014-11-02 15:48:49 【问题描述】:进程 A 向进程 B 发送 signalfd。当 B 尝试 read() 时会发生什么?如果B将signalfd添加到epoll中,epoll_wait什么时候返回?
【问题讨论】:
显示让你提出问题的源代码。 请解释如何将signalfd
获得的文件描述符发送到另一个进程。因此,请编辑您的问题以改进它。
-1,因为您没有改进您的问题。
+1 问题是明确的,是一个有趣的问题(我试图自己回答)。 FD 在进程之间传递的方法无关紧要,只会给问题增加噪音。另一种可能的方式是从父级继承到子级。
@kenton-varda signalfd read()
在当前线程的信号队列上工作。 epoll我不知道,但是poll和select会使用当前线程的信号队列。
【参考方案1】:
手册页中有一条线索:
fork(2) 语义
在 fork(2) 之后,子进程继承了 signalfd 文件描述符的副本。从子文件描述符中读取 (2) 将返回有关排队到子进程的信号的信息。
signalfd
s 通过 unix 套接字传输的行为应该与 fork()
继承的行为相同。基本上,哪个进程创建了signalfd
是无关紧要的;来自它的read()
ing 总是将排队的信号返回给调用read()
的进程。
与epoll
有一个奇怪的交互,但是:由于epoll
事件队列是在任何特定进程的上下文之外管理的,它根据最初称为@987654329 的进程决定signalfd
的就绪状态@注册对signalfd
的兴趣。所以如果你安排看signalfd
和epoll
FD,然后将两个FD都发送到另一个进程,接收进程会看到不一致的结果:epoll
只会在发送进程有信号时发出准备就绪信号,但是signalfd
将为接收进程返回信号。
这种情况使用fork()
特别容易上手。例如,如果你初始化一个事件循环库而不是使用epoll
和signalfd
,然后调用fork()
(例如守护进程),然后尝试在子进程中使用该库,你可能会发现你无法接收信号。 (我昨天花了一整天的时间来调试这样的问题。)
【讨论】:
【参考方案2】:这是不一致的,或者至少是记录不足的极端情况。 仔细阅读signal(7)。
进程 A 可以使用 kill(2) 或 killpg(2) 向进程 B 发送 信号(不是 signalfd)。
进程 B 正在处理一个信号(并且有一些默认行为来处理一些信号)。它可以使用旧的signal(2) 或更新的sigaction(2) 安装(以POSIX 标准的方式)信号处理程序,或者它可以通过使用signalfd(2) 来询问(以Linux 特定的方式)以获取文件描述符上的一些数据.
所以signalfd
成功时会提供一个新的文件描述符,例如open
或socket
do。
阅读signalfd(2)
文档,它解释了读取时 B 端发生的情况(内核正在发送一些 struct signalfd_siginfo
,我想从进程获取信号的角度来看,而不是进程读取文件描述符,查看内核的源文件fs/signalfd.c),或者在signalfd
给出的文件描述符上使用poll
或epoll等待;当 B 接收到信号时,轮询将成功。
一个成功的 signalfd
只是获得一个打开的文件描述符(就像文件描述符 open
、socket
、accept
、pipe
给你的那样),你赢了t 与不相关的进程共享该文件描述符。
如果您敢在使用unix(7) 的套接字上使用sendmsg(2)
将文件描述符发送到其他进程,我不会做出任何假设。我猜它类似于pipe(7)-s 或fifo(7)-s 或netlink(7)-s。但我当然不会那样做:signalfd
是特定于 Linux 的,而您处于未记录极端情况。阅读内核源代码以了解发生了什么,或在kernelnewbies 上提问。并且不要期望太多未来的内核在未记录的方面与当前内核的行为一致......
【讨论】:
因为我想知道如果在一个进程中创建的 signalfd 被发送到另一个进程并在那里使用会发生什么。在文档中read(2)
为“进程”返回 signalfd_siginfo。是调用进程还是创建signalfd的进程?以上是关于将 signalfd 发送到另一个进程的主要内容,如果未能解决你的问题,请参考以下文章
将结构从一个进程发送到另一个进程的最简单方法是啥? [关闭]