在前一个完成时分离更多进程,直到达到最大值

时间:2017-03-29 05:01:00

标签: c++ c process fork waitpid

要分叉X进程并让父进程等待,我有以下代码:

int maxProcesses = 10;

for (int currentChild = 0; currentChild < maxProcesses; currentChild++) {
    pid_t pid = fork();

    if (pid < 0) {
        // Error
    } else if (pid == 0) {
        // Child
    } else {
        // Parent
        // Should I call waitpid on pid and wait here instead?
    }
}

// Wait for all children
for (int currentChild = 0; currentChild < maxProcesses; currentChild++) {
    wait(NULL);
}

现在我想修改代码,以便在X总进程中,Y首先分叉,然后当它们完成时,会产生更多的分叉,直到达到所需的总数。我已经对上面的代码进行了一些更改,并提出了一些问题。

int totalProcessesToBeForked = 10;
int maxAllowedAtOnce = 5;

for (int currentChild = 0; currentChild < maxAllowedAtOnce; currentChild++) {
    forkChild(currentChild);
}

// Wait for all children
// # How do I modify this to wait for new children forked as well
// # if I move it inside parent, it will make things easier, right?
for (int currentChild = 0; currentChild < maxAllowedAtOnce; currentChild++) {
    wait(NULL);
}

void forkChild(currentChild) {
    pid_t pid = fork();

    if (pid < 0) {
        // Error
    } else if (pid == 0) {
        // Child
    } else {
        // Parent
        // # I think waiting here using waitpid will be better b/c
        // # as new forks are made, parent begins to wait for them
    }
}

我可能需要计算已分叉的子项数并将其与totalProcessesToBeForked进行比较,并相应地分叉新的子项。

更新了代码v1:

int maxProcesses = 10;
int maxAllowedAtOnce = 5;

int main(int argc, char* argv[]) {
    // Start timer
    alarm(10);                  // Terminate after 10s
    signal(SIGALRM, onTimeout);
    signal(SIGCHLD, catchChild);

    for (int currentChild = 0; currentChild < maxAllowedAtOnce; currentChild++) {
        forkChild(currentChild);
    }

    // # This sections runs immediately before death of any child is reported
    // # and starts cleanup processes, thus killing any/all running children

    // Completed before timeout
    endTimer = true;
    int timeRemaining = alarm(0);
    if (timeRemaining > 0) {
        printf("\nCompleted w/ %is remaining. Performing cleanup.\n", timeRemaining);

        // Kill children any running child processes, cleanup
        cleanup();
    }

    return 0;
}

void forkChild(currentChild) {
    pid_t pid = fork();

    if (pid < 0) {
        // Error
    } else if (pid == 0) {
        // Child
        execl("/bin/date", "date", 0, 0);
    } else {
        // Parent
        printf("#Log: Started %i.\n", currentChild + 1);
    }
}

void catchChild(int sig) {
    pid_t p;
    int state;
    p=wait(&state);
    printf("Got child %d\n",p);
}

void cleanup() {
    // Cleanup Code
}

示例运行:

enter image description here

编辑#2: http://ideone.com/noUs3m

1 个答案:

答案 0 :(得分:1)

不要像你一样使用wait,而是想要查看信号处理来处理死亡的子进程。

在开始fork之前添加,此行

signal(SIGCHLD,catchchild);

这个函数代码

void catchchild(int sig)
  {
  pid_t p;
  int state;
  p=wait(&state);
  printf("Got child %d\n",p);
  }

然后,只要子进程终止,您的主进程就会调用catchchild

正如您已经解决的那样,如果您计算了分叉的子女数量,您可以catchchild更新,以便您的主要代码知道fork一个新的孩子。

回答您的评论,如下所示,除了更多错误检查

while(totalProcessesToBeForked)
  {
  if(currentChild < maxAllowedAtOnce)
    {
    forkChild(currentChild);
    totalProcessesToBeForked--;
    }
  sleep(1);
  }