我有一个难闻的问题:
我有这样的代码:
int main()
{
pid_t child, parent;
int status=0;
int i;
printf("parent = %d\n", getpid());
for(i=1; i<=5; i++){
if( (child = fork()) == 0){
sleep(i);
printf("i=%d, %d\n",i, getpid());
}
}
wait(0);
while( (parent = wait(&status)) > 0){
printf("Exit = %d, child = %d\n", status/256, parent);
}
}
输出类似于:
1, 21320
2, 21321
Exit = 0, child = 21321
3, 21322
Exit = 0, child = 21322
4, 21323
Exit = 0, child = 21323
5, 21324
Exit = 0, child = 21324
我认为wait(0)不是等待所有子进程,而是只等待第一次退出并写入all (Exit = ...)。
有任何方法可以做到这一点:
1, 21320
2, 21321
3, 21322
4, 21323
5, 21324
Exit = 0, child = 21320
Exit = 0, child = 21321
Exit = 0, child = 21322
Exit = 0, child = 21323
Exit = 0, child = 21324
发布于 2014-03-16 08:33:16
这不是wait()
的问题,而是同步的问题--或者说缺乏同步。每次调用fork()
时,子进程都会休眠一段时间,但父进程会继续执行。当大多数子进程仍在休眠时,父进程完成其fork循环并开始等待循环,因此每次其中一个子进程退出时,父进程就已经在等待它了。这就是为什么父进程能够在每个子进程退出后立即打印其退出消息的原因。
如果您希望父进程在进入wait()
循环之前等待所有子进程完成睡眠,则需要使用进程间通信同步机制(如POSIX semaphores )使父进程阻塞,直到所有子进程都通知它们已准备就绪为止。
然而,如果您的目标仅仅是让所有的退出消息出现在屏幕上的子ID消息之后,那么您实际上根本不需要延迟wait()
调用。只需更改wait
循环,将状态值存储在数组中,而不是立即打印它们,然后在wait
循环结束后,运行另一个循环来打印数组的内容。
发布于 2014-03-16 08:40:00
下面是按照您要求的顺序生成输出的最简单方法的演示。它使用3个循环:一个用于创建子进程,一个用于等待它们并收集它们的退出状态,还有一个用于打印退出状态。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define NUMPROC 5
int main(void)
{
pid_t child[NUMPROC];
int status[NUMPROC];
int i;
printf("parent = %d\n", getpid());
for(i=0;i<NUMPROC;++i) {
if(fork() == 0) {
sleep(i);
printf("i=%d, %d\n",i, getpid());
_exit(0);
}
}
for(i=0;i<NUMPROC;++i)
child[i] = wait(&status[i]);
for(i=0;i<NUMPROC;++i)
printf("Exit = %d, child = %d\n", WEXITSTATUS(status[i]), child[i]);
}
发布于 2014-03-16 08:20:12
wait (0)
等待任何子进程更改状态,而不是等待所有进程更改状态。您必须存储子进程的pid,然后在for循环中等待每个进程:
i_am_child = 0;
my_i = 0;
for (i = 0; i < nr_children; ++i) {
child = fork ();
if (child == 0) { i_am_child = 1; my_i = i; break; }
childpid [i] = child;
}
if (i_am_child) {
// do what children are supposed to do, e.g. printf and sleep (my_i)
exit (0);
}
if (! i_am_child) // strictly, this line is not necessary, since children have exited
for (i = 0; i < nr_children; ++i) waitpid (childpid [i], &status, 0);
...
确保fork和waits只由父进程执行!
据我所知,孩子们应该在fork之后立即进入第一个break
循环,而不是进入第二个循环。
https://stackoverflow.com/questions/22431386
复制相似问题