C waitpid()函数返回错误(-1),为什么?
我正在用C编写一个类似Linux shell的程序 除此之外,我正在实现两个内置命令:C waitpid()函数返回错误(-1),为什么?,c,linux,process,waitpid,C,Linux,Process,Waitpid,我正在用C编写一个类似Linux shell的程序 除此之外,我正在实现两个内置命令:jobs,history. 在jobs中,我打印当前正在工作的命令列表(在后台)。 在history中,我打印到目前为止所有命令历史记录的列表,指定每个命令是正在运行还是已完成 为了实现这两个,我的想法是创建一个命令列表,将命令名映射到它们的PID。调用jobs/history命令后,我将遍历它们,检查哪些正在运行或已完成,并相应地打印 我在网上读到,函数:waitpid(pid,&status,WNOHANG
jobs,history.
在jobs
中,我打印当前正在工作的命令列表(在后台)。
在history
中,我打印到目前为止所有命令历史记录的列表,指定每个命令是正在运行还是已完成
为了实现这两个,我的想法是创建一个命令列表,将命令名映射到它们的PID。调用jobs/history命令后,我将遍历它们,检查哪些正在运行或已完成,并相应地打印
我在网上读到,函数:waitpid(pid,&status,WNOHANG)
可以从“pid”检测进程是否仍在运行或已完成,而无需停止进程。
除此之外,它运行良好:
当程序处于活动状态时,函数将返回该程序。
当一个程序完成时,我第一次调用它时返回done,从那时起,如果再次使用相同的PID调用,它将返回-1(错误)
例如,它将如下所示:(&symbols-background命令)
而且,这些都不受我之前或之后可能执行的其他命令调用的影响,上面描述的行为似乎独立于其他命令
我在网上读到了waitpid
可能返回-1的各种原因,但在我的案例中我无法确定原因。此外,我还试图了解它是什么类型的waitpid
错误,但同样没有成功
我的问题是:
这个问题的一个解决方案是,一旦我“完成”,我就将命令签名为“完成”,并且在打印之前不再对其执行
waitid
。这将解决问题,但我不知道为什么会发生这种情况您应该熟悉Unix环境中如何处理子进程。特别是阅读有关
当一个进程死亡时,它进入“僵尸”状态,因此它的PID仍然保留,并唯一地标识现在已经死亡的进程。僵尸进程上成功的等待
将释放进程描述符及其PID。因此,在同一PID上对wait
的后续调用将失败,因为该PID上没有其他进程(除非为新进程分配了相同的PID,在这种情况下,等待它将是一个逻辑错误)
您应该重新构造程序,以便在等待
成功并报告某个进程已完成
时,您可以将该信息记录在自己的数据结构中,并且不再在该PID上调用等待
为了进行比较,一旦流程完成,bourne shell将最后一次报告该流程,然后将其从作业列表中删除:
$ sleep 10 &
$ jobs
[1] + Running sleep 10
$ jobs
[1] + Running sleep 10
$ jobs
[1] Done sleep 10
$ jobs
$
由于C和shell的混合,我感到困惑。你检查了errno吗?@at77谢谢你的建议,得到:“无子进程”手册页上说:如果:ECHILD pid指定的进程不存在或不是调用进程的子进程,waitpid()函数将失败,或者pid指定的进程组不存在,或者没有作为调用进程的子进程的任何成员进程。我认为发生的是,当程序完成时,它的状态被查询,它将从子进程列表中删除。谢谢,我能够解决这个问题,因为在某个进程上返回done(并将其视为done)后,我不再检查waitpid()。非常感谢!这其实是我在网上所了解的,但我想在这方面得到保证。现在,我的解决方案是添加到“job”结构和id,如果正在运行,则表示1,如果完成,则表示0。我只在运行的元素上检查waitpid()。如果waitpid()返回DONE,我会将id更改为0,并且不再检查。@spano:这样做很好。在释放僵尸“作业”结构时,您还需要思考:)
$ sleep 10 &
$ jobs
[1] + Running sleep 10
$ jobs
[1] + Running sleep 10
$ jobs
[1] Done sleep 10
$ jobs
$