【问题标题】:Waitpid acting as if in non-blocking modeWaitpid 就像在非阻塞模式下一样
【发布时间】:2019-06-30 05:15:49
【问题描述】:

我正在玩 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) 并按照 cmets 中的建议打印了 waitpid 的输出。这里没有打印,waitpid 打印 -1

【问题讨论】:

  • 你确定你的 exec() 调用成功了吗?添加对 exit(1) 的调用;紧接着,万一失败了……
  • 首先检查waitpid 返回什么。如果它返回零,则检查t2 的值以了解子进程的退出代码。不要忘记检查execvp 是否也返回。
  • 我尝试按照你们的建议进行操作。控制流不低于 execvp 并且 waitpid 返回 -1。
  • 如果 waitpid() 返回 -1,您应该打印出 errno 以查看失败的原因(perror()strerror() 可用于获取人类可读的错误消息,而不是神秘数字)

标签: c operating-system system-calls pid waitpid


【解决方案1】:

问题是竞争条件。这里分叉后:

a = fork();

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

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

然后父母在这里等待:

waitpid(-a,&t2,0);

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

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

【讨论】:

    猜你喜欢
    • 2012-12-11
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 2012-01-14
    • 2013-11-04
    • 2013-10-20
    相关资源
    最近更新 更多