C waitpid()函数返回错误(-1),为什么?

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

我正在用C编写一个类似Linux shell的程序

除此之外,我正在实现两个内置命令:
jobs,history.
jobs
中,我打印当前正在工作的命令列表(在后台)。 在
history
中,我打印到目前为止所有命令历史记录的列表,指定每个命令是正在运行还是已完成

为了实现这两个,我的想法是创建一个命令列表,将命令名映射到它们的PID。调用jobs/history命令后,我将遍历它们,检查哪些正在运行或已完成,并相应地打印

我在网上读到,函数:
waitpid(pid,&status,WNOHANG)
可以从“pid”检测进程是否仍在运行或已完成,而无需停止进程。 除此之外,它运行良好:

当程序处于活动状态时,函数将返回该程序。 当一个程序完成时,我第一次调用它时返回done,从那时起,如果再次使用相同的PID调用,它将返回-1(错误)

例如,它将如下所示:(&symbols-background命令)

而且,这些都不受我之前或之后可能执行的其他命令调用的影响,上面描述的行为似乎独立于其他命令

我在网上读到了
waitpid
可能返回-1的各种原因,但在我的案例中我无法确定原因。此外,我还试图了解它是什么类型的
waitpid
错误,但同样没有成功

我的问题是:

  • 你认为为什么会发生这种行为
  • 如果你有一个解决方案(理想的做法是让它继续返回完成)
  • 如果您对如何实现jobs/history命令有更好的了解,则可以接受

  • 这个问题的一个解决方案是,一旦我“完成”,我就将命令签名为“完成”,并且在打印之前不再对其执行
    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
    $