【问题标题】:waitpid() function returns ERROR (-1), why?waitpid() 函数返回 ERROR (-1),为什么?
【发布时间】: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 错误的类型,但再次失败。

我的问题是:

  1. 您认为为什么会发生这种行为
  2. 如果您有解决方案(理想的做法是让它不断返回 DONE)
  3. 如果您对如何实现作业/历史命令有更好的了解,我们会接受

此问题的一个解决方案是,一旦我得到“DONE”,我将命令签署为 DONE,并且在打印之前不再对其执行waitid。这将解决问题,但我仍不知道为什么会发生这种情况

【问题讨论】:

  • 由于C和shell的混合,我很困惑。
  • 你检查errno了吗?
  • @at77 感谢您的建议,得到:“没有子进程”
  • 手册页说: waitpid() 函数将在以下情况下失败: ECHILD pid 指定的进程不存在或不是调用进程的子进程,或 pid 指定的进程组不存在存在或没有任何成员进程是调用进程的子进程。我认为正在发生的是,当程序完成并查询其状态时,它会从子进程列表中删除。
  • 谢谢,一旦 waitpid() 在某个进程上返回 DONE(并将其视为已完成),我就可以通过不再检查 waitpid() 来解决问题。

标签: c linux process waitpid


【解决方案1】:

您应该熟悉在 Unix 环境中如何处理子进程。特别要阅读Zombie processes

当一个进程死亡时,它会进入一个“僵尸”状态,因此它的 PID 仍然是保留的,并且唯一地标识了现在已经死亡的进程。在僵尸进程上成功的wait 会释放进程描述符及其 PID。因此,在同一 PID 上对 wait 的后续调用将失败,因为没有更多具有该 PID 的进程(除非为新进程分配了相同的 PID,在这种情况下等待它是一个逻辑错误)。

您应该重新构建您的程序,以便如果 wait 成功并报告进程是 DONE,您将该信息记录在您自己的数据结构中,并且不再在该 PID 上调用 wait

为了比较,一旦一个进程完成,bourne shell 最后一次报告它,然后将它从作业列表中删除:

$ sleep 10 &
$ jobs
[1] + Running                 sleep 10
$ jobs
[1] + Running                 sleep 10
$ jobs
[1]   Done                    sleep 10
$ jobs
$

【讨论】:

  • 非常感谢!这实际上是我在网上所理解的,但希望对此有所保证。我现在的解决方案是添加到“作业”结构和 id,如果正在运行则表示 1,如果完成则表示 0。我只在运行元素上检查 waitpid() 。如果 waitpid() 返回 DONE,我将 id 更改为 0 并且不再检查。
  • @spano:这是一个很好的方法。当你释放你的僵尸“工作”结构时,你还需要考虑:)
猜你喜欢
  • 2014-02-28
  • 1970-01-01
  • 2021-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-16
  • 2021-12-22
  • 1970-01-01
相关资源
最近更新 更多