当bg停止进程时,Bash(和其他shell)如何处理分离STDIN?

时间:2018-12-03 10:23:42

标签: bash shell signals zsh jobs

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

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

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

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

这是我的研究陷入僵局的地方。因此,我对其他外壳如何处理此类问题感兴趣。

以下是一些参考资料,以帮助解释在上面的描述不太清楚的情况下我要做什么:

[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

1 个答案:

答案 0 :(得分:1)

我的理解:

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