【问题标题】:Creating n childs process with fork() and treat them after使用 fork() 创建 n 个子进程并在之后处理它们
【发布时间】:2021-12-13 12:14:09
【问题描述】:

我想在 for 循环中通过 fork() 创建 n 个子进程,并在子进程全部创建后处理。子进程必须在 父进程执行完毕。

    int main(int argc, char *argv[])
{
    char cadena[STRLONG];

    pid_t pid;
    
    for(int i =0; i<5; i++){
        pid = fork();

        if(pid == -1){
            perror("Error\n");
            exit(-1);
        }
        else if(pid == 0){
            break;
        }
    }

    if (pid > 0){
        printf("I'm the parent, --> %d\n", getpid());
    }
    else if(pid == 0){
        printf("I'm the child --> %d \n", getpid());
        exit(0);
    }
    for(int i = 0; i<5; i++){
        wait(NULL);
    }
}

这是我做的,但是子进程在全部创建之前就执行了,不知道怎么解决……

【问题讨论】:

  • fork 会立即启动子进程。停止执行的唯一方法是添加进程间信号量或类似的东西,让孩子们在信号量上等待。
  • 可能将您的程序的输出添加到问题中,然后解释为什么它的行为不符合您的预期
  • 一个选项可能是创建一个由所有子级继承的管道。在完成所有子代的分叉后,父代可以向管道写入 5 个字节(每个子代一个字节),而子代可以阻塞,直到他们从管道中读取一个字节后再执行其他操作。
  • @IanAbbott 旧管道技巧。好的!不过,通常只需关闭管道就足够了。
  • angel bn:如果你有什么想让我在我的回答中进一步解释的,尽管问,我会尽量说得更清楚。

标签: c fork child-process


【解决方案1】:

当你fork()时,父子进程会立即从你fork()的地方并行运行。

time     parent      child
 |         |
 |         |
 |       fork()--------+
 |         |           |
 V         |           |    ​

没有办法知道他们中的哪一个在另一个之前做某事 - 除非你以某种方式同步他们的动作。

要在进程之间进行适当的同步,您可以使用 信号量 或其他一些进程间通信技术。对于这个简单的案例,您可以使用旧的self-pipe trick

  • 创建一个pipe
  • 创建子代后,关闭子代中pipe 的写入端 - 并尝试从pipe 中读取一个字节。这将一直挂起,直到有一个字节或 pipe 关闭。
  • 创建完所有子项后,关闭父项中的阅读端。
  • 此时的状态应该是:
    • 父级仅打开了pipe 的写入端。
    • 所有孩子都只打开pipe的阅读端,急切地等待pipe中发生的事情。
  • 当父级希望所有子级都开始工作时,关闭父级中pipe 的写入端。这将导致所有子级中的read 操作解除阻塞。

下面没有错误检查,但它会显示这个想法:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

enum { P_RD, P_WR }; // pipe indices, 0 and 1

int main() {
    pid_t pid;

    int pip[2];
    pipe(pip); // create a pipe from pip[P_WR] to pip[P_RD]

    for(int i = 0; i < 5; i++) {
        pid = fork();

        if(pid == -1) {
            perror("Error\n");
            exit(1);
        } else if(pid == 0) {
            close(pip[P_WR]);        // close write end of pipe
            char ch;                 // dummy buffer
            read(pip[P_RD], &ch, 1); // hang here until closed
            close(pip[P_RD]);        // close read end of pipe

            printf("I'm the child --> %d \n", getpid());
            exit(0);
        }
    }
    close(pip[P_RD]); // close read end of pipe

    // The state at this point:
    // * The parent only has the write end of the pipe open.
    // * All the children only have the read end of the pipe open.

    printf("I'm the parent --> %d\n", getpid());
    close(pip[P_WR]); // close write end of pipe to start children

    int wstatus;
    while((pid = wait(&wstatus)) != -1) {
        printf("%d died\n", pid);
    }
}

【讨论】:

  • 我喜欢信号量,+1 先生
  • @clockw0rk 好的,谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多