`SIGWINCH` 是如何通过 Bash 的?

How does `SIGWINCH` pass through Bash?

如果我 运行 Bash 中的一个程序侦听 SIGWINCH,并且我调整 Bash 正在 运行 的终端的大小,然后该程序将收到 SIGWINCH。我想知道这个信号是如何中继到 Bash.

下的程序 运行ning 的

这是我对所发生情况的理解,使用我在本文末尾列出的示例 catch_sig 程序 post:

然而,我在上面遇到的一个困难是,如果我尝试使用 kill 手动将 SIGWINCH 发送到 Bash 的进程组,那么 catch_sig 收不到信号。例如,如果 Bash 的 PID(和进程组)是 123 并且我 运行 catch_sig 在其中,然后我 运行 kill -WINCH -123 在单独的窗格中,然后 catch_sig 没有收到信号。为什么会这样?

下面是演示catch_sig程序的源代码,如上所述:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>

static void sigwinch_handler(int sig) {
        printf("got signal: %d\n", sig);
}

int main() {
        signal(SIGWINCH, sigwinch_handler);
        printf("waiting for signal...\n");
        pause();
        return 0;
}

For example, if the PID (and process group) for Bash is 123 and I run catch_sig in it, and then I run kill -WINCH -123 in a separate pane, then catch_sig doesn't receive the signal. Why is this this the case?

终端仅向前台(即控制)进程组发送SIGWINCH。当 Bash 为 interactive 时,每个作业(前台或后台)都被放置在一个单独的进程组中,前台作业暂时获得终端的控制权。例如:

1 号航站楼:

$ tty
/dev/pts/0
$ echo $$
123
$ ./catch_sig
waiting for signal...

2 号航站楼:

$ ps -t /dev/pts/0 -o pid,pgid,stat,comm
  PID  PGID STAT COMMAND
  123   <b>123</b> S<s  bash
  124   <b>124</b> <b>S<+</b>  catch_sig

STAT字段中的加号(+)表示该进程是前台进程组的成员,参见ps(1)

因此,当您调整终端 window 的大小时,而 catch_sig 在前台 运行(即它的进程组被 Bash 设为前台进程组),而且还没有完成),SIGWINCH 只发送到 catch_sig 的进程组。然后 Bash 在 catch_sig 终止时重新获得终端的控制权。

可以使用 kill 复制,如下所示。

2 号航站楼:

$ kill -WINCH -124

1 号航站楼:

got signal: 28

有关详细信息,请参阅 how job control is implemented in POSIX shells