- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
为特定信号指定处理程序的经典方法是通过 sigaction
。 Linux 还提供了 signalfd
功能,我们可以在其中将信号连接到文件描述符,然后将 select/(e)poll 应用于该描述符,这非常适合许多事件循环驱动系统的概念。
我想知道当两种机制发生冲突时会发生/应该发生什么。可以有竞争条件吗?在 signalfd 联机帮助页 ( http://man7.org/linux/man-pages/man2/signalfd.2.html ) 上,我们读到:
Normally, the set of signals to be received via the file descriptor should be blocked using sigprocmask(2), to prevent the signals being handled according to their default dispositions.
因此,它说“通常”我们使用信号掩码以防止(默认)处理程序处理信号。它并没有说当我们有一个文件描述符连接到它时,我们必须阻止该信号。不幸的是,手册页没有具体说明当我们不阻止信号时会发生什么。
这看起来像是定义不明确的行为。我不相信这实际上没有明确定义,并且想知道这里是否有人知道i)我能找到关于系统应该如何运行的详细规范或ii ) 它的行为方式。
我特别感兴趣的是这个执行顺序:
这是未定义的行为还是必须发生的事情有标准/规范?处理程序是否总是优先于文件描述符?处理程序是否调用了 和 文件描述符触发了一个事件?设置 sigaction
是否会更改信号掩码,从而不需要渲染步骤 (2)?
我可以尝试从涉及实际代码的系统测试中推导出实际行为。然而,我当然更愿意找到一份详细的文档,并认为我自己无法找到正确的引用资料。
最佳答案
signalfd
的行为与 sigwaitinfo
相同,只是您可以通过文件描述符访问信息。这意味着 signalfd
接收信号同步,并且信号处理程序(或默认配置)被调用首先。
来源: TLPI 第 22.10 和 22.11 章(M. Kerrisk)。
行为定义明确,但未必符合预期,联机帮助页的措辞相当糟糕。说“通常...应该” 表明您实际上不必这样做,或者更糟的是作者不太确定。
如果你想让它“正常”工作,即你通常期望的方式(看,我也使用“正常”),你必须阻止信号。否则,信号将通过文件描述符可用,但仍将首先调用处理程序(这是完全合法的,但大多数人可能会认为这是“奇怪的行为”)。
因此,存在两种不同的竞争条件。一个条件是您询问的条件,但尽管该行为有点出乎意料,但它定义明确且(有点)记录在案,如果您考虑一下,那么它并不是严格意义上的竞争条件。而是一种“双重交付”。
另一个竞争条件是在您创建 signalfd
之后但在您阻止信号之前信号到达的可能性。这是不太可能的,但原则上,这可能会发生。幸运的是,解决方案很简单,您可以先阻塞信号,然后创建文件描述符(如果中间有信号到达,文件描述符将立即准备就绪)。
您命名的命令序列(创建文件描述符、解锁,然后是 sigaction
)具有类似的竞争条件。您应该先安装一个处理程序然后解除阻塞,否则可能会在处理程序到达之前传递信号。但这与 signalfd
无关。文件描述符在任何情况下仍可用于读取信号,但如果信号在解除阻塞和安装处理程序之间到达,则默认配置可能会终止进程。
关于linux - signalfd 和 sigaction 之间可以竞争吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20228092/
我在一些代码中看到以下用法: struct sigaction term_handler; // global variable without initialization ... sigacti
我正在做简单的 sigaction 示例来练习 C,但是当我尝试编译代码时,它声称 struct sigaction 不存在 [1]。 当我检查我生成的一些旧代码时,我发现我在文件的最顶部添加了一些
如果我们使用 sigaction 来定义一个信号处理程序,那为什么我们不需要重置处理程序呢?如果我们使用 signal(sig_no,handler_func)那么我们必须重置它。为什么是这样? #i
我正在学习信号并编写了一个简单的程序来处理它们。 所以我输入一个数字,然后使用 fork 创建一个进程。父进程应该将数字作为信号发送给子进程,然后 child_signal 处理程序应该将数字的平方作
我在 C++ 中对此类使用 sigaction 时遇到问题: class SerialHandler{ private: ... /* Action Handling
我有以下 sigaction 处理程序代码 void signal_term_handler(int sig) { int rc = async_lockf(pid_file, F_UNLCK
我正在使用 sigaction 作为信号,我正在为此使用一个简单的结构。我实际上是从手册页中获取的。有人可以向我解释结构中的第二行是做什么的吗?还有一个错误: error: expected decl
有没有办法用sigaction结构和函数只捕获一次信号?更具体地说,我想简单地重置为默认特定信号 (SIGINT)。是否有可能在处理程序中实现这一点? 编辑 所以,这样的事情是正确的: void si
我正在将程序的信号处理从 signal() 转换为 sigaction()。 根据UNIX spec struct sigaction 应该至少有 4 个成员; sa_handler、sa_mask、
我很难理解 sigaction() 的方式有效。 在 , sigaction 定义为 int sigaction(int sig, const struct sigaction *act, struc
我正在查看 sigaction 的手册页,最后我看到了以下行。 sigaction(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
在我下面的代码中,如果我将 old_act 声明为全局变量,那么程序可以正常工作。如果在 main 中声明: 如果使用 SA_RESTART,它工作正常 如果不使用 SA_RESTART,则会导致段错
我必须向进程发送两个信号,SIGUSR1 和 SIGUSR2,以便修改程序中的特定 bool 变量 (SIGUSR1 将其设置为 true,SIGUSR2 将其设置为 false)。所以我写了一个 s
我正要向我们这里的应用程序添加一个额外的信号处理程序,我注意到作者使用了 sigaction() 来设置其他信号处理程序。我打算使用 signal()。按照惯例,我应该使用 sigaction(),但
编译以下代码, struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = &handler; sigaction (SIGR
我有一个程序,它为 SIGSEGV 安装信号处理程序。在信号处理程序中(我 try catch 崩溃)我重新启动我的应用程序。 但是当我的应用程序复活时,它不再处理 SIGSEGV。 这是一个例子:
我注意到 sigaction 被定义为结构和函数(http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html):
每次收到 SIGINT 时,我都使用 sigaction() 执行操作。我见过的所有教程都使用这个原型(prototype)作为信号处理程序 void sig_handler(int sig); 有没
这个问题在这里已经有了答案: What is it with printf() sending output to buffer? (3 个答案) 关闭 3 年前。 我是 Unix 中信号的新手,这
我正在尝试以下信号处理程序,引用在线教程,但它似乎不起作用,我的代码有什么问题: #include #include #include #include #include typedef void (
我是一名优秀的程序员,十分优秀!