waitpid() 函数 returns ERROR (-1),为什么?
waitpid() function returns ERROR (-1), why?
我正在用 C 编写一个 Linux shell 类程序。
除其他外,我正在执行两个内置命令:jobs, history.
在 jobs
中,我打印了当前工作命令的列表(在后台)。
在 history
中,我打印了到目前为止所有命令历史记录的列表,并为每个命令指定它是 运行 还是完成。
为了实现这两个,我的想法是有一个命令列表,将命令名称映射到它们的 PID。调用 jobs/history 命令后,我 运行 通过它们,检查哪些是 运行ning 或已完成,并相应地打印。
我在网上看到函数:waitpid(pid, &status, WNOHANG)
,可以在不停止进程的情况下从“PID”检测进程是否仍在 运行ning 或完成。
它运行良好,除了这个:
当程序处于活动状态时,函数 return 执行它。
当一个程序完成时,我第一次称它为 returns done,从那时起,如果使用相同的 PID 再次调用它,它会 returns -1 (ERROR).
例如,它看起来像这样:(& 表示后台命令)
$ 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
可能 return -1 的各种原因,但我无法确定我的情况的原因。此外,我尝试寻找如何理解 waitpid
错误的类型,但再次失败。
我的问题是:
- 您认为为什么会发生这种行为
- 如果您有解决方案(理想情况是它保持 returning DONE)
- 如果你对如何实现有更好的想法jobs/history命令被广泛接受
这个问题的一个解决方案是,一旦我得到“DONE”,我就将命令签署为 DONE,并且在打印它之前不再对其执行 waitid
。这将解决问题,但我对为什么会发生这种情况一无所知
您应该熟悉在 Unix 环境中如何处理子进程。特别是阅读 Zombie processes.
当一个进程死亡时,它进入'zombie'状态,因此它的PID仍然被保留并唯一标识现在死亡的进程。僵尸进程上的成功 wait
会释放进程描述符及其 PID。因此,在同一 PID 上对 wait
的后续调用将失败,因为不再有具有该 PID 的进程(除非为新进程分配了相同的 PID,在这种情况下等待它是一个逻辑错误)。
您应该重构您的程序,以便如果 wait
成功并报告进程 DONE
,您将该信息记录在您自己的数据结构中并且永远不会调用 wait
再次在那个 PID 上。
为了比较,一旦一个进程完成,bourne shell 最后一次报告它,然后将其从作业列表中删除:
$ sleep 10 &
$ jobs
[1] + Running sleep 10
$ jobs
[1] + Running sleep 10
$ jobs
[1] Done sleep 10
$ jobs
$
我正在用 C 编写一个 Linux shell 类程序。
除其他外,我正在执行两个内置命令:jobs, history.
在 jobs
中,我打印了当前工作命令的列表(在后台)。
在 history
中,我打印了到目前为止所有命令历史记录的列表,并为每个命令指定它是 运行 还是完成。
为了实现这两个,我的想法是有一个命令列表,将命令名称映射到它们的 PID。调用 jobs/history 命令后,我 运行 通过它们,检查哪些是 运行ning 或已完成,并相应地打印。
我在网上看到函数:waitpid(pid, &status, WNOHANG)
,可以在不停止进程的情况下从“PID”检测进程是否仍在 运行ning 或完成。
它运行良好,除了这个:
当程序处于活动状态时,函数 return 执行它。 当一个程序完成时,我第一次称它为 returns done,从那时起,如果使用相同的 PID 再次调用它,它会 returns -1 (ERROR).
例如,它看起来像这样:(& 表示后台命令)
$ 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
可能 return -1 的各种原因,但我无法确定我的情况的原因。此外,我尝试寻找如何理解 waitpid
错误的类型,但再次失败。
我的问题是:
- 您认为为什么会发生这种行为
- 如果您有解决方案(理想情况是它保持 returning DONE)
- 如果你对如何实现有更好的想法jobs/history命令被广泛接受
这个问题的一个解决方案是,一旦我得到“DONE”,我就将命令签署为 DONE,并且在打印它之前不再对其执行 waitid
。这将解决问题,但我对为什么会发生这种情况一无所知
您应该熟悉在 Unix 环境中如何处理子进程。特别是阅读 Zombie processes.
当一个进程死亡时,它进入'zombie'状态,因此它的PID仍然被保留并唯一标识现在死亡的进程。僵尸进程上的成功 wait
会释放进程描述符及其 PID。因此,在同一 PID 上对 wait
的后续调用将失败,因为不再有具有该 PID 的进程(除非为新进程分配了相同的 PID,在这种情况下等待它是一个逻辑错误)。
您应该重构您的程序,以便如果 wait
成功并报告进程 DONE
,您将该信息记录在您自己的数据结构中并且永远不会调用 wait
再次在那个 PID 上。
为了比较,一旦一个进程完成,bourne shell 最后一次报告它,然后将其从作业列表中删除:
$ sleep 10 &
$ jobs
[1] + Running sleep 10
$ jobs
[1] + Running sleep 10
$ jobs
[1] Done sleep 10
$ jobs
$