1

我的程序应该将子进程的数量限制为 3。

使用下面的代码,waitpid我的父进程停止,因此我无法在第一个子进程之后创建更多子进程。如果我不使用waitpid,那么我不知道子进程何时退出以减少活动进程的数量。

int numProcs = 0;
while(1==1) {
    /* 
     * inserts code that waits for incoming input 
     */
    numProcs++;
    pid = fork();
    if (pid == 0) {
        doStuff(); // may exit anytime, based on user input
    } else {
        if (numProcs > 3) {
            wait(&status);
            numProcs--;
        } else {
            waitpid(pid, &status, 0); // PROBLEM!
            numProcs--;
        }
    }
}

我整天都在寻找这个问题。有人可以帮忙吗?

4

2 回答 2

3

冒着明显的风险,您基本上只想删除 else 子句。您正在寻找的逻辑是这样的:

int max_active = 3; // or whatever
int number_active = 0;
bool done = false;

for (; !done; ++number_active) {
  // wait for something to do;
  GetSomeWork();
  // wait for something to finish, if necessary.
  for (; number_active >= max_active; --number_active)
    wait(&status);
  pid = fork();
  if (pid < 0)
    ReportErrorAndDie();
  if (pid == 0)
    DoTheWorkAndExit();
}

这实际上让您可以在不重新启动的情况下更改 max_active 的值,这是围绕 wait() 调用的 for 循环的唯一理由。

明显的抱怨是我的版本中的 number_active 实际上并没有告诉你有多少进程处于活动状态,这是真的。它告诉你有多少进程没有等待(),这意味着你可能会保留一些僵尸(但数量有限)。如果您始终以或接近最大任务数运行,这无关紧要,除非您的最大值很大,否则无论如何都没关系,因为唯一的设计要求是您使用的任务数不超过任务的最大数量,因此您只需要知道活动的数量不超过最大值。

如果这真的困扰您并且您想清理任务,您可以放置​​:

for (; waitpid(-1, &status, WNOHANG) > 0; --number_active) {}

在另一个 for 循环之前,它将在检查是否需要阻止之前收割僵尸。(如果根本没有进程,我不记得 waitpid(-1, &status WNOHANG) 是否返回错误,但无论如何,在出现错误时继续循环是没有意义的。)

于 2012-09-25T22:11:10.297 回答
0

您的代码有两个问题,但第二个问题被第一个掩盖了。

您的直接问题是 waitpid(pid, &status, 0); 将阻塞,直到具有指定 pid 的进程终止。您想将 WNOHANG 选项作为第三个参数添加到 waitpid() 调用中。这将确保调用不会阻塞。

这将增加一个新问题:您必须自己检查是否有任何子进程已终止。您可以使用 WIFEXITED 宏来做到这一点:

} else {
  waitpid (-1, &status, WNOHANG);
  if (WIFEXITED(status)) {
    numProcs--;
  }
}

第二个问题是您的原始代码只等待创建最新的 pid。您应该等待 -1,这是所有子进程。

于 2012-09-25T22:11:30.407 回答