linux - 程序的作业感知 shell 与作业不感知 shell 执行

标签 linux shell unix ipc

当我在阅读 APUE v3 时,更具体地说,我发现自己无法掌握一些东西。 首先,假设我在 UNIX shell 中运行以下管道程序:

cat /etc/passwd | grep -i alex | awk -F : '{print $3}' | less

在第一个示例中,我们假设我正在使用作业感知 shell (sh)

这本书解释说,在这种情况下,最终的 ps -o pid,ppid,pgid,comm 看起来像这样(假设 shell 的 pid 是 10,它的 ppid 是 5)

PID     PPID     PGID     COMM
10       5       10        sh
11       10      10        less
12       11      10        cat /etc/passwd
13       11      10        grep -i alex
14       11      10        awk -F : '{print $3}'

在第二个示例中,假设我们使用的是作业感知 shell (bash):

PID      PPID     PGID     COMM
10       5       10        bash
11       10      11        cat /etc/passwd
12       10      11        grep -i alex
13       10      11        awk -F : '{print $3}'
14       10      11        less

问题是,为什么在第二种情况下,进程是 shell 的子进程,而不是最后一个进程的子进程(如第一种情况),并假设 shell 为它的每个子进程接收一个 SIGCHLD, child 之间不会出现某种竞争条件吗?

附言。抱歉缩进错误。我现在会尝试修复它 谢谢, 亚历克斯

最佳答案

The question is, why in the second case, the processes are the children of the shell, and not of the last process [...]

因为这是正确的行为。只有 shell 中的错误才能解释为什么 less 会成为管道中其他进程的父进程。 less 无法处理其他进程的 SIGCHLD,因为它还没有启动它们。 (此外,由于 less 中的系统调用因 EINTR 错误而失败,这也会导致问题。)这也意味着除了 less 之外的所有进程都将被 PID 1 回收,而不是 shell,因为它会收到它们的 SIGCHLD

否则,进程的父子关系与“作业感知 shell ”无关。作业感知 shell 做两件事:它实现作业控制(jobsfgbg 命令)并将自己设置为 session 领导者(使用 setsid() 系统调用)以便在它(shell)终止时自动将 SIGHUP 发送到所有子进程。

[...] and presuming that shell receives a SIGCHLD for each of it's children, doesn't some kind of race condition occur between the children?

竞争条件是指事情没有按照预期的顺序执行的情况。在这里,没有预期的顺序。大多数过滤器应用程序(如 grep 的过滤器:从 stdin 读取,写入 stdout)一旦在 stdin 上看到 EOF 就会终止。经常发生的情况是,管道中的第一个进程可能在最后一个进程看到任何输入时已经终止。这是正常的。他们被收割了,但他们的输出已经被发送到管道中并且会被正常处理。

关于linux - 程序的作业感知 shell 与作业不感知 shell 执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20596910/

相关文章:

linux - 从 Linux 主机触发 Visual Studio 构建

c - OS X 中的 fp->_IO_write_base 和 fp->_IO_write_end

c - Unix 信号量问题

regex - 可以[一个| b] 在 grep BRE 模式下使用表达式?

c - 使用 Pipe() 时,子进程如何向父进程返回两个值?

c - 无符号变量表现得像有符号

linux - 测试网关最简单的方法是什么?

bash - Vim:打开文件后读取模式行?

shell - 如何将批处理(CALL)命令的输出存储到变量

python - 如何为 supervisord 设置 PATH 以便它找到可执行文件