【发布时间】:2019-01-01 08:34:01
【问题描述】:
我正在编写一个具有一些类似于 shell 的功能的 C 程序,其中包括在后台通过 readline 接口启动的子进程中运行的程序。
我目前遇到的一个问题是,一旦我生成了这样的子进程并再次开始输入输入字符,这些字符就会被生成的子进程通过标准输入接收。这并不奇怪,因为我在分叉后没有修改子文件描述符,而且我理解这意味着它们都与主进程共享STDIN_FILENO 下的相同流。
然而,这不是我想要的。我希望我的程序表现得像例如bash 在这方面,在后台启动正在进行的进程后重新获得提示后,在该提示上键入的任何字符都只会被 bash 看到,而不会被生成的进程看到。这就是我的问题所在,因为我什至不明白 bash 是如何做到的。查看/proc/.../fd/0 的bash 以及任何衍生的进程,它们总是指向同一个伪终端。只需将生成的进程 stdin 重定向到例如/dev/null 显然也会产生不同的行为。
这里我不需要完整的实现,只是一个一般性的提示。
编辑:我刚刚发现,如果我使用带有O_RDWR 标志的open 命令打开/dev/null,则将stdin 重定向到/dev/null 会起作用。
然后,我的程序似乎按照我想要的方式运行,只是当我运行 ps 时,以这种方式启动的子进程显示为 <defunct>。我不确定为什么会这样。
编辑:我想我现在已经弄清楚了,最简单的方法似乎是创建一个伪终端从站,然后将孩子的标准输入重定向到它:
int master;
int slave;
openpty(&master, &slave, nullptr, nullptr, nullptr);
dup2(slave, STDIN_FILENO);
【问题讨论】:
-
看看 heirloom bourne shell 如何处理作业可能更容易,因为在
jobs.c中运行约 800 行 C 代码,而在“太大太慢”中运行约 3,300 行重击 -
我会这样做的。我相信
<defunct>只是由于线程中等待子进程的错误,但无论如何,看看更专业的实现可能是个好主意。