在 fork() 之后卡在 wait()
Stuck on wait() after fork()
我看了一些关于这个的话题,但没能解决 -
我分叉了两次,但是在等待最后一个过程时它卡在了 wait() 上,如果我删除 wait() 它会继续,但显然它不会等待:
相关代码如下:
/*Fork #1*/
if((pid=fork())==0)
{
if(command -> inputRedirect != NULL)
{
fclose(stdin);
fopen(command -> inputRedirect,"r");
}
fclose(stdout);
dup(pipefd[1]);
close(pipefd[1]);
i=execvp(command->arguments[0],command->arguments);
}
if(i == -1)
{
perror("Error");
return 1;
}
printf("\nParent: %d , Child: %d\n",getpid(),pid);
command = command->next;
/*Fork #2*/
if((pid=fork())==0)
{
fclose(stdin);
dup(pipefd[0]);
close(pipefd[0]);
if(command -> outputRedirect != NULL)
{
fclose(stdout);
fopen(command ->outputRedirect,"w");
}
i=execvp(command->arguments[0],command->arguments);
_exit(0);
}
if(i == -1)
{
perror("Error");
return 1;
}
if(command->blocking == 1)
{
int test=0;
printf("\nParent: %d , Child: %d\n",getpid(),pid);
printf("\ntest1\n");
while((test=wait(NULL)) != pid)
{
printf("\n %d \n ", test);
}
printf("\ntest2\n");
}
return 0;
}
我添加了一些测试来查看一些 PID 输出以及内部发生了什么,它等待第一个 chil 进程完成,并打印正确的 ID,但在第二个上它只是阻塞。
但是我确实在屏幕上看到第二个进程已完成(从进程输出)。
欢迎就此主题提供任何帮助。
谢谢。
进程在没有未收集的children时调用wait()
是错误的(wait()
将return-1
并设置errno
到 ECHILD
),所以 wait()
挂起的事实表明 是 一个 child 进程集。一旦 child 进程实际上已经终止——包括如果它在 wait()
调用之前已经终止——parent 进程就可以进行调度并且应该 return 立即从wait()
。因此,wait()
调用挂起是一个很好的迹象,表明两个 child 进程之一实际上还没有退出。
正如我在评论中所写,child 的输出不一定是它是否已退出的可靠指示。 child退出时会变成僵尸,直到被收集为止,可以在table.
进程中查看
您的文件描述符处理看起来有点奇怪,这可能是您问题的根源。首先,如果你想将管道 FD 复制到 children 的标准流上,那么你应该使用 dup2()
来明确指定,而不是 close()
+ dup()
.不过,更可能是您的实际问题是 parent 进程未能关闭其管道 FD 的副本。如果第二个 child 正在等待其标准输入(来自管道)上的 EOF,那么 parent 未能关闭其管道写入端的副本将阻止 child 从终止。
我看了一些关于这个的话题,但没能解决 -
我分叉了两次,但是在等待最后一个过程时它卡在了 wait() 上,如果我删除 wait() 它会继续,但显然它不会等待:
相关代码如下:
/*Fork #1*/
if((pid=fork())==0)
{
if(command -> inputRedirect != NULL)
{
fclose(stdin);
fopen(command -> inputRedirect,"r");
}
fclose(stdout);
dup(pipefd[1]);
close(pipefd[1]);
i=execvp(command->arguments[0],command->arguments);
}
if(i == -1)
{
perror("Error");
return 1;
}
printf("\nParent: %d , Child: %d\n",getpid(),pid);
command = command->next;
/*Fork #2*/
if((pid=fork())==0)
{
fclose(stdin);
dup(pipefd[0]);
close(pipefd[0]);
if(command -> outputRedirect != NULL)
{
fclose(stdout);
fopen(command ->outputRedirect,"w");
}
i=execvp(command->arguments[0],command->arguments);
_exit(0);
}
if(i == -1)
{
perror("Error");
return 1;
}
if(command->blocking == 1)
{
int test=0;
printf("\nParent: %d , Child: %d\n",getpid(),pid);
printf("\ntest1\n");
while((test=wait(NULL)) != pid)
{
printf("\n %d \n ", test);
}
printf("\ntest2\n");
}
return 0;
}
我添加了一些测试来查看一些 PID 输出以及内部发生了什么,它等待第一个 chil 进程完成,并打印正确的 ID,但在第二个上它只是阻塞。
但是我确实在屏幕上看到第二个进程已完成(从进程输出)。
欢迎就此主题提供任何帮助。
谢谢。
进程在没有未收集的children时调用wait()
是错误的(wait()
将return-1
并设置errno
到 ECHILD
),所以 wait()
挂起的事实表明 是 一个 child 进程集。一旦 child 进程实际上已经终止——包括如果它在 wait()
调用之前已经终止——parent 进程就可以进行调度并且应该 return 立即从wait()
。因此,wait()
调用挂起是一个很好的迹象,表明两个 child 进程之一实际上还没有退出。
正如我在评论中所写,child 的输出不一定是它是否已退出的可靠指示。 child退出时会变成僵尸,直到被收集为止,可以在table.
进程中查看您的文件描述符处理看起来有点奇怪,这可能是您问题的根源。首先,如果你想将管道 FD 复制到 children 的标准流上,那么你应该使用 dup2()
来明确指定,而不是 close()
+ dup()
.不过,更可能是您的实际问题是 parent 进程未能关闭其管道 FD 的副本。如果第二个 child 正在等待其标准输入(来自管道)上的 EOF,那么 parent 未能关闭其管道写入端的副本将阻止 child 从终止。