【问题标题】:How does Bash (and other shells) handle detaching STDIN when `bg`ing a stopped process?`bg` 停止进程时,Bash(和其他 shell)如何处理分离 STDIN?
【发布时间】:2018-12-03 10:23:42
【问题描述】:

我正在编写自己的 shell,并且我支持作业控制[1](类似于 jobs)。我可以停止进程,在前台和后台恢复它们[2]。这一切都在很大程度上按预期工作 - 至少从用户的角度来看。

但是我遇到的问题是,在后台恢复工作时,任何从 STDIN 读取的应用程序都会与 readline 竞争(我实际上已经编写了自己的 readline API,原因超出了这个问题的范围),这会破坏可用性贝壳。

我承认这些情况很少见,但我的理解是,通常应该发生的情况是任何需要从 STDIN[3] 读取的后台进程都发送 SIGTTIN[4] 信号。

我的问题是如何监控从 STDIN 读取的应用程序 - 以便在需要时发送 SIGTTIN?

这就是我的研究走到了尽头的地方。所以我对其他 shell 如何处理这类问题很感兴趣。

如果上面的描述不是很清楚,以下是一些参考资料,可帮助解释我正在尝试做的事情:

[1]https://en.wikipedia.org/wiki/Job_control_(Unix)#Overview

[2]https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bg.html

[3]https://en.wikipedia.org/wiki/Job_control_(Unix)#Implementation

[4]https://en.wikipedia.org/wiki/Signal_(IPC)#SIGTTIN

【问题讨论】:

  • 这不是 shell 的一部分,但是系统例如在后台启动的 tr 命令tr 01 10 & 将被停止,因为尝试从标准输入读取并在后台运行
  • 然而停止并不意味着在 fg %1 或它继续的作业 ID 之后终止
  • 是的,“停止”的术语有点误导,但我已经确定了那部分。然而,听起来我需要重新编写我所有的作业控制逻辑,因为我目前正试图在 shell 中处理它,而不是让内核去做这件事并设置进程组。

标签: bash shell signals zsh jobs


【解决方案1】:

我的理解:

  • shell 通常是分配控制终端的会话领导者。
  • 每个作业(可能有多个进程,例如ls | wc -l)都是一个进程组。
  • 只有前台 pgrp 可以从控制终端读取。 (fg pgrp 可能有多个进程,这些进程可以同时从控制端读取。)
  • shell 调用 tcsetpgrp() 来设置前台 pgrp(例如,当我们开始一个新作业,或者使用 fg 将 bg 作业放回 fg 时)。
  • 内核(tty 驱动程序)将SIGTTIN 发送到试图从控制终端读取数据的后台进程。
  • shell 不知道进程何时会从控制终端读取。相反,shell 监控作业的状态变化。当进程被SIGTTIN 停止时,shell 会收到SIGCHLD,然后它可以调用waitpid() 以获取更多信息。

【讨论】:

  • 听起来我现在做错了很多,因为我正在捕获信号,然后将它们转发到相关进程,而不是让进程自己处理信号而不是分配进程组。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 2015-04-12
  • 2022-09-23
  • 2020-11-19
  • 2011-02-09
  • 2016-11-17
  • 2015-07-24
相关资源
最近更新 更多