我正在使用 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。当我使用 -a 作为参数调用 waitpid 时,我基本上要求它等待(阻塞)直到 pgid=a 中的任何进程完成。然而,程序的输出并不是我所期望的!子进程根本没有被收获。就好像 waitpid 处于非阻塞模式。输出:
Parent pid = 11372
Child pid = 11373
11373
(输出是瞬时的,不会等待10秒!)
编辑:我在 execvp 下面添加了 printf("Here")
和 exit(1)
并按照注释中的建议打印出 waitpid 的输出。这里没有打印,而 waitpid 打印 -1
最佳答案
问题是竞争条件。在这里 fork 之后:
a = fork();
如果子进程首先运行,则在此处创建进程组-a
:
if(a==0){
setpgid(getpid(),getpid());
然后家长在这里等待:
waitpid(-a,&t2,0);
但是如果父进程先运行,进程组-a
确实不存在,并且waitpid()
失败,并显示 ECHILD
。第二种情况显然发生在您的系统上。
您必须找到某种方法来确保子进程中的setpgid()
调用在waitpid()
之前运行叫来家长。复杂的方法是信号量,简单(hacky)的方法是短暂的延迟,在 waitpid()
之前的 usleep(1)
可能就足够了。
关于c - Waitpid 的行为就像处于非阻塞模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54550459/