作业感知外壳与作业不感知外壳执行程序

Posted

技术标签:

【中文标题】作业感知外壳与作业不感知外壳执行程序【英文标题】:Job aware shell vs job unaware shell execution of programs 【发布时间】:2013-12-15 16:36:27 【问题描述】:

在阅读 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,孩子之间不会发生某种竞争条件吗?

PS。对不起,错误的缩进。我现在会尝试修复它 谢谢, 亚历克斯

【问题讨论】:

在这里试图抓住你的问题......你的意思是在孩子们死亡之间的竞争条件,让他们有可能不按时间顺序死亡吗?在任何一种情况下(由shell),命令都会按顺序处理,所以AFAIK这不应该造成问题...... 【参考方案1】:

问题是,为什么在第二种情况下,进程是 shell 的子进程,而不是最后一个进程的子进程 [...]

因为这是正确的行为。只有 shell 中的错误可以解释为什么 less 会成为管道中其他进程的父进程。 less 无法处理其他进程的 SIGCHLD,因为它还没有启动它们。 (更重要的是,由于less 中的系统调用因 EINTR 错误而失败,这也会导致问题。)这也意味着除less 之外的所有进程都将由 PID 1 而非 shell 获取,因为它将接收它们的SIGCHLD.

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

[...] 并假设 shell 为它的每个孩子接收一个 SIGCHLD,孩子之间不会发生某种竞争条件吗?

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

【讨论】:

以上是关于作业感知外壳与作业不感知外壳执行程序的主要内容,如果未能解决你的问题,请参考以下文章

实验一 感知器及其应用

实验一 感知机及其应用

Delphi - Indy TIdHTTP方式创建程序外壳 - 实现可执行程序的自动升级

加密与解密之加壳程序

Programming In Lua 第一章

实验一