【问题标题】:background process catching process id before termination后台进程在终止前捕获进程 ID
【发布时间】:2013-09-14 17:30:34
【问题描述】:

我正在尝试在 C 中模拟后台和前台进程。这样做时,如果最后有一个“&”符号,我会避免在父进程中等待该子进程。我还将我执行的所有后台命令存储在一个列表中,并在完成后尝试将它们从列表中删除。但是在 ls -l& 的情况下,输出会立即显示,只需按 enter 即可终止进程。如果它与列表中的现有 pid 匹配,如何捕获该进程 id 并从我的列表中删除。

pid = fork();
//Code to add pid into a list if it is a background process
//this is done by parent as pid is always 0 for child processes
if(pid == 0){
    if(proc_state=='&'){
        setsid();           
    }
        // logic for creating command
        int ret= execvp( subcomm[0], subcomm );
    // handling error
}

//Parent will execute this
//Child will never come here if execvp executed successfully

if(proc_sate != '&'){
        for(i=0; i < count_pipe+1; i++){            
            int ret = waitpid(0, &flag ,0);
        // Code to remove procid from list if 'ret' matches with existing procid in the list.
        }
}

//Here proc_state just determines whether it is background or foreground.It is just a character. count_pipe is just a 
//variable holding number of pipes

希望我清楚。如有疑问请提出问题

【问题讨论】:

  • 我删除了 C++ 标签。
  • ls -l&amp; 立即显示其输出有什么问题?这就是在大多数贝壳中会发生的情况。 pipe_count 到底是什么,为什么它与你 waitpid() 的次数有关?
  • 捕获execvp() 的返回值没有任何好处,因为它总是-1。如果函数返回,则失败。如果成功,则不会返回。失败原因在errno。还要注意,无论execvp() 是否成功,注释//Child will never come here 都应该为真;孩子永远不应该回到父进程的代码中。 // handling error 代码应始终为 exit()_exit() 并且不返回。 (所有分类陈述都应该用一点盐来处理,但 99.x% 的时间都是准确的。)

标签: c shell unix


【解决方案1】:

通常,您会在如下循环中使用waitpid()

int status;
pid_t corpse;

while ((corpse = waitpid(0, &status, WNOHANG)) != -1)
{
    /* Process PID of child that died with given status */
    ...
}

这会收集所有死去的孩子,但在没有更多尸体可收集时返回。选项 0 表示“我的进程组中任何死去的孩子”;另一种选择 -1 表示“任何死去的孩子”。在其他情况下,您可以指定特定的 PID 以查看该子进程是否已死亡,或者使用负数指定进程组中 PGID 等于绝对值的任何子进程。

WNOHANG 的意思是“如果目前没有尸体死亡,不要等待孩子死去”;使用 0 表示“等到适当类别的孩子死亡”,尽管当没有这样的孩子时调用会返回。

如果进程组中有多个子进程,则无法保证返回尸体的顺序,就像无法保证子进程死亡的顺序一样。

您的要求是什么并不完全清楚。例如,您可以根据最后启动的管道是否在后台运行来选择waitpid() 的最后一个参数。如果您之前在后台启动了一个进程,您几乎可以在任何时候收集它的尸体(除非您正在等待不同的进程组,或该后台 PID 之外的特定 PID)。您可能会根据具体情况选择不同的 waitpid() 的第一个参数。

【讨论】: