【问题标题】:When several signals arrive at a process, what is the order between the process handling the signals?当多个信号到达一个进程时,处理这些信号的进程之间的顺序是什么?
【发布时间】:2018-06-01 02:52:42
【问题描述】:

当多个信号到达一个进程时,处理这些信号的进程之间的顺序是什么?

用什么数据结构来存储已经到达进程但还没有被传递的信号?

例如,来自 APUE

由于进程组在父进程终止时成为孤立进程,POSIX.1 要求向新孤立进程组中停止的每个进程(就像我们的子进程一样)发送挂断信号(SIGHUP)后跟 继续信号 (SIGCONT)

这会导致子进程在处理挂断信号后继续。这 挂断信号的默认动作是终止进程,所以我们必须 提供一个信号处理程序来捕获信号。因此,我们期望 printf 在 sig_hup 函数出现在 pr_ids 函数中的 printf 之前。

正如https://stackoverflow.com/a/17769300/156458 所说

在子进程恢复执行之前,无法传递 SIGHUP。 当一个进程停止时,所有的信号传递都会暂停,除了 SIGCONT 和 SIGKILL。

因此,SIGHUP 确实首先到达,但它无法被处理直到 SIGCONT 唤醒进程执行。

SIGHUP 在 SIGCONT 之前到达已停止的进程。 SIGHUP 不能被释放,而 SIGCONT 可以。

SIGCONT 是在 SIGHUP 之前还是之后处理的?第一个引号似乎是“之后”,而第二个引号似乎是“直到”的“之前”。

如果“之前”:

  • 如何安排 SIGCONT 跳到 SIGHUP 之前交付?

  • SIGCONF 在释放之前跳转,SIGHUP 如何不被丢弃?

以上是基于FIFO队列或者FILO栈等一些数据结构实现的吗?

谢谢。

【问题讨论】:

    标签: linux algorithm data-structures signals


    【解决方案1】:

    这种情况可能会因不同的实现和 POSIX 实时信号的引入而混淆。 http://man7.org/linux/man-pages/man7/signal.7.html 表示实时信号与旧式信号的区别在于

    实时信号以有保证的顺序传递。多 同类型的实时信号按顺序送达 他们被派去。如果不同的实时信号被发送到一个 过程中,它们从编号最小的开始交付 信号。 (即,编号低的信号具有最高优先级。) 相反,如果一个进程有多个标准信号待处理, 它们的交付顺序未指定。

    与巴赫的“Unix 操作系统的设计”中描述的旧式信号一样(在引入 POSIX 实时信号之前)。

    为了向进程发送信号,内核在进程表条目的信号字段中设置一个位,对应于接收到的信号类型。 ...当进程从内核模式返回到用户模式并以适当的低信号优先级离开睡眠状态时,内核会检查是否接收到信号。

    您可以在https://github.com/torvalds/linux/blob/master/include/linux/sched.h 看到一些当前的 linux 数据结构。看着这个我怀疑旧式位图已经消失了,位图和链表的组合用于处理旧式和 POSIX 实时信号,但我没有通过足够多的代码来确定这一点.

    【讨论】:

      【解决方案2】:

      添加到 mcdowella 的回复中:

      1) “信号处理”的细节可能因平台而异

      2)在Linux的具体情况下:

      http://man7.org/linux/man-pages/man7/signal.7.html

      Linux 支持两种 POSIX 可靠信号(以下称为“标准 信号”)和 POSIX 实时信号。

      3) 另见:

      【讨论】:

        【解决方案3】:

        SIGCONT 具有特殊的语义。

        无论 SIGCONT 是否被捕获、被忽略或具有默认处置,它的生成都会清除所有挂起的停止信号并恢复执行已停止的进程。 [IEEE Std 1003.1-2017] 同样,这种恢复发生在任何其他信号传递之前,甚至在调用 SIGCONT 的处理程序(如果有)之前。

        (这种特殊的“无处置”语义是有意义的。为了让进程执行信号处理程序,进程本身必须正在执行。)

        这里POSIX比APUE更清楚,说的是"[t]he default action for SIGCONT is to resume execution at the point where the process was stopped, after first handling any pending unblocked signals."

        正如其他人所提到的,传递待处理信号的实际顺序是特定于实现的。至少,Linux 按数字升序提供基本的 UNIX 信号。

        为了演示这一切,请考虑以下代码。它停止一个进程,然后向它发送几个信号,然后继续它,为所有可捕获的信号安装了处理程序,因此我们可以看到在以下情况下处理了什么:

        #define _POSIX_SOURCE
        #include <signal.h>
        #include <sys/types.h>
        #include <unistd.h>
        #include <stdlib.h>
        #include <stdio.h>
        
        static int signals[] = { SIGSTOP, SIGURG, SIGUSR1, SIGHUP, SIGCONT, 0 };
        
        static void
        handler(int signo) {
          // XXX not async-signal-safe
          printf("<signal %d>\n", signo);
        }
        
        int
        main(int argc, char **argv) {
          int *sig = signals;
          struct sigaction sa = { .sa_flags = 0, .sa_handler = handler };
        
          sigfillset(&sa.sa_mask);
        
          sig++; // can't catch SIGSTOP
          while (*sig) {
            sigaction(*sig, &sa, NULL); // XXX error check
            sig++;
          }
        
          if (fork() == 0) { // XXX error check
            sleep(2);        // faux synchronization - let parent pause()
        
            sig = signals;
            while (*sig) {
              printf("sending signal %d\n", *sig);
              kill(getppid(), *sig);
              sig++;
            }
            exit(0);
          }
        
          pause();
        
          return 0;
        }
        

        对我来说,这是打印出来的

        sending signal 19
        sending signal 23
        sending signal 10
        sending signal 1
        sending signal 18
        <signal 1>
        <signal 10>
        <signal 18>
        <signal 23>
        

        【讨论】:

        • 谢谢。 (1) “这种恢复发生在任何其他信号被传递之前,甚至在之前 SIGCONT 的处理程序(如果有的话)被调用。”和“[t] SIGCONT 的默认操作是在进程停止的点恢复执行,首先处理任何未决的未阻塞信号。” “之前”和“之后”是相反的吗? “之后”是什么意思?
        • (2) “Linux 不同于对前面 POSIX 引用的严格阅读,因为 SIGCONT (#18) 处理程序在 SIGURG (#23) 处理程序之前被调用。”既然 18 小于 23,难道 SIGCONT 和 SIGURG 在 Linux 中是按预期升序传递的吗? “分歧”是什么意思?
        • (3)既然SIGHUP是1,SIGCONT是18,那么SIGHUP不应该在SIGCONT之前送吗?为什么实际上是先传递SIGCONT来恢复进程,然后传递SIGHUP?
        • @Tim,模棱两可。乍一看 POSIX 引用,我预计 SIGCONT 本身——它的用户信号处理程序——将在所有其他未决信号之后最后处理。不过,我的阅读内容似乎不是你的,所以我会更新并删除我的观点。
        猜你喜欢
        • 2015-06-15
        • 2014-07-04
        • 1970-01-01
        • 2014-04-05
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-19
        相关资源
        最近更新 更多