当我在阅读 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 做两件事:它实现作业控制(jobs
、fg
、bg
命令)并将自己设置为 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/