首页 > 解决方案 > Waitpid 就像在非阻塞模式下一样

问题描述

我正在玩 C 中的系统调用,我一直试图理解我制作的这个程序 -

int main(int argc, char* argv[])
{
int a;
char *args[]={"sleep"," 10",NULL}; 

a = fork();
int stat;


if(a==0){
    setpgid(getpid(),getpid());
    printf("%d\n",getpgid(getpid()));
    execvp(args[0],args);}
else
{
    int t2;
    waitpid(-a,&t2,0);
}

printf("Parent pid = %d\n", getpid()); 
printf("Child pid = %d\n", a); 

}

据我了解,我已经将child的pgid设置为自己的pid。当我waitpid使用 -a 作为参数调用时,我基本上要求它等待(阻塞)直到 pgid=a 中的任何进程完成。然而,程序的输出并不是我所期望的!子进程根本没有被收割。就好像 waitpid 处于非阻塞模式一样。输出:

Parent pid = 11372
Child pid = 11373
11373

(输出是瞬时的,它不会等待 10 秒!)

编辑:我在 execvp 下方添加printf("Here")exit(1)打印出 waitpid 的输出,如评论中所建议的那样。这里没有打印,waitpid 打印 -1

标签: coperating-systemsystem-callspidwaitpid

解决方案


问题是竞争条件。在此处分叉后:

a = fork();

如果孩子首先运行,-a则在此处创建进程组:

if(a==0){
    setpgid(getpid(),getpid());

然后父母在这里等待:

waitpid(-a,&t2,0);

但如果进程首先运行,则进程组-a还不存在,并且waitpid()失败并显示ECHILD. 第二种情况显然发生在您的系统上。

您必须找到某种方法来确保子调用在父调用之前setpgid()运行。复杂的方式是信号量,简单的(hacky)方式是短暂的延迟,然后可能就足够了。waitpid()usleep(1)waitpid()


推荐阅读