【发布时间】:2021-03-28 16:10:47
【问题描述】:
我正在用 C 编写一个类似于 Linux shell 的程序。
除其他外,我正在实现两个内置命令:jobs, history.
在jobs 中,我打印当前工作命令的列表(在后台)。
在history 中,我打印了迄今为止所有命令历史记录的列表,并为每个命令指定它是 RUNNING 还是 DONE。
为了实现这两者,我的想法是有一个命令列表,将命令名称映射到它们的 PID。一旦调用了作业/历史命令,我就会运行它们,检查哪些正在运行或已完成,并进行相应的打印。
我在网上看到函数:waitpid(pid, &status, WNOHANG),可以从“PID”中检测进程是否仍在运行或完成,而无需停止进程。
它工作得很好,除了这个:
当程序处于活动状态时,函数将其返回。 当一个程序完成时,我第一次调用它时会返回 done,从那时起,如果再次使用相同的 PID 调用它,它会返回 -1(错误)。
例如,它看起来像这样:(& 表示后台命令)
$ sleep 3 &
$ jobs
sleep ALIVE
$ jobs (withing the 3 seconds)
sleep ALIVE
$ jobs (after 3 seconds)
sleep DONE
$ jobs
sleep ERROR
$ jobs
sleep ERROR
....
此外,这些不受我之前或之后可能执行的其他命令调用的影响,似乎上述行为与其他命令无关。
我在网上阅读了 waitpid 可能返回 -1 的各种原因,但我无法确定我的情况的原因。另外,我尝试寻找如何理解 waitpid 错误的类型,但再次失败。
我的问题是:
- 您认为为什么会发生这种行为
- 如果您有解决方案(理想的做法是让它不断返回 DONE)
- 如果您对如何实现作业/历史命令有更好的了解,我们会接受
此问题的一个解决方案是,一旦我得到“DONE”,我将命令签署为 DONE,并且在打印之前不再对其执行waitid。这将解决问题,但我仍不知道为什么会发生这种情况
【问题讨论】:
-
由于C和shell的混合,我很困惑。
-
你检查errno了吗?
-
@at77 感谢您的建议,得到:“没有子进程”
-
手册页说: waitpid() 函数将在以下情况下失败: ECHILD pid 指定的进程不存在或不是调用进程的子进程,或 pid 指定的进程组不存在存在或没有任何成员进程是调用进程的子进程。我认为正在发生的是,当程序完成并查询其状态时,它会从子进程列表中删除。
-
谢谢,一旦 waitpid() 在某个进程上返回 DONE(并将其视为已完成),我就可以通过不再检查 waitpid() 来解决问题。