首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Linux fork()和wait()

Linux fork()和wait()
EN

Stack Overflow用户
提问于 2014-03-16 08:10:47
回答 4查看 11.2K关注 0票数 4

我有一个难闻的问题:

我有这样的代码:

代码语言:javascript
运行
复制
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);
    }    
}

输出类似于:

代码语言:javascript
运行
复制
    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 = ...)。

有任何方法可以做到这一点:

代码语言:javascript
运行
复制
    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
EN

回答 4

Stack Overflow用户

发布于 2014-03-16 08:33:16

这不是wait()的问题,而是同步的问题--或者说缺乏同步。每次调用fork()时,子进程都会休眠一段时间,但父进程会继续执行。当大多数子进程仍在休眠时,父进程完成其fork循环并开始等待循环,因此每次其中一个子进程退出时,父进程就已经在等待它了。这就是为什么父进程能够在每个子进程退出后立即打印其退出消息的原因。

如果您希望父进程在进入wait()循环之前等待所有子进程完成睡眠,则需要使用进程间通信同步机制(如POSIX semaphores )使父进程阻塞,直到所有子进程都通知它们已准备就绪为止。

然而,如果您的目标仅仅是让所有的退出消息出现在屏幕上的子ID消息之后,那么您实际上根本不需要延迟wait()调用。只需更改wait循环,将状态值存储在数组中,而不是立即打印它们,然后在wait循环结束后,运行另一个循环来打印数组的内容。

票数 4
EN

Stack Overflow用户

发布于 2014-03-16 08:40:00

下面是按照您要求的顺序生成输出的最简单方法的演示。它使用3个循环:一个用于创建子进程,一个用于等待它们并收集它们的退出状态,还有一个用于打印退出状态。

代码语言:javascript
运行
复制
#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]);
}
票数 4
EN

Stack Overflow用户

发布于 2014-03-16 08:20:12

wait (0)等待任何子进程更改状态,而不是等待所有进程更改状态。您必须存储子进程的pid,然后在for循环中等待每个进程:

代码语言:javascript
运行
复制
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循环,而不是进入第二个循环。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22431386

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档