我浏览了示例和手册页,但无法弄清楚 signalfd 和 sigwaitinfo 之间的区别除了语法之外,两者都在做同样的事情,即等待信号将其详细信息存储到某种结构中。
在手册页中是这样写的。这提供了使用信号处理程序或 sigwaitinfo(2)的替代方法 ,并且具有可以通过 select(2)、poll(2) 和 epoll(7) 监视文件描述符的优点。
谁能解释一下这到底是什么意思?
Bru*_*ger 10
select(2)、poll(2) 和 epoll(7) 系统调用只是一种等待文件描述符(代表 I/O 通道的小整数)事件的方法。事件可以包括“读取数据”、“准备写入”等。你的代码组成了一组文件描述符,这些描述符最终会有一个事件,然后调用 select()、或 poll() 或 epoll() 使程序等待直到数据到达,内核将套接字连接到其他主机, 一个描述符有错误,无论如何。
signalfd(2) 添加了一个新事件:信号到达。在 unix/linux/*BSD 中,“信号”是一个或多或少的异步事件:CPU 尝试执行非法指令,I/O 就绪,代码除以零,调制解调器挂断。signalfd(2) 允许您创建一个文件描述符,可在 select()、poll()、epoll() 中使用,在信号到达时具有事件。
过去,您会指定一个处理程序函数,当信号到达时内核会神奇地调用它(也称为“上行调用”)。如果您使用 sigaction() 系统调用告诉内核您希望它调用什么函数,您将获得与 sigwaitinfo() 相同的信息。
使用 signal() 或 sigaction() 设置处理函数而不是 signalfd() 的区别在于,处理函数可以在任何时候神奇地被调用:您的代码的一部分必须是可重入的(不仅仅是线程安全的,请注意您)处理信号的“随时”性质。使用signalfd(),信号只是代码事件循环中要处理的另一个事件。您的代码只是照常执行。
sigwaitinfo() 使您的代码暂停,直到您指定的信号到达时为止。在该信号到达之前,您的代码什么都不做。没有事件循环,什么都没有。看起来 sigwaitinfo() 也是 Linux 内核中实时内容的一部分。sigwaitinfo() 可以被认为是在代码中指定一个位置供内核在信号到达时调用,而不是指定要调用的函数。
添加:
我刚刚发现了一篇关于“自管技巧”的博客文章。显然,不仅在代码方面处理信号和基于选择的 I/O 不方便,您还可能遭受“讨厌的竞争条件”。自管道技巧通过基本上做signalfd(2) 所做的事情来解决这个问题,但所有这些都在用户空间中,并且以更多代码为代价。