c - 使用 fork() 和管道的进程环

标签 c linux process pipe

一个小时以来,我一直在绞尽脑汁地思考这个问题。我必须创建一个包含 n 个进程的进程环(数量通过 cmd 作为参数传递)。父进程将他的 PID 发送给他的第一个子进程,这个进程将他父进程的 PID 加上他自己的 PID 发送给他的下一个兄弟,直到我们创建了 n 个子进程。之后,父进程将获得其所有子进程的 PID。

假设父进程的 PID 为 3400,我们创建了两个子进程,因此环由三个进程组成

3400 + 3401(第一个子进程的 PID)+ 3402(第二个子进程的 PID)= 10203

父进程应该得到这个10203。

我考虑过一个“for”循环,其中子进程仅使用一个管道将其兄弟 PID 的添加从一个兄弟发送到另一个兄弟。尽管如此,我还没有找到解决方案。

最佳答案

鉴于任务是使用 fork()pipe(),您可能需要使用如下算法:

  • 父级创建管道以写入第一个st子级。
  • 父级保持向第一个st子级打开管道的写入端。
  • 父级保持第 N 个子级的管道读取端处于打开状态。
  • 对于每个 child n = 1..N,家长为第 n 个 child 创建输出管道,以便与第 n+1 对话。
  • 父进程 fork 第 n 个子进程。
  • 第 n 个子进程关闭其输入管道的写入端和输出管道的读取端。
  • 第 n 个子进程从输入管道读取 PID 总和,将自己的 PID 添加到总和中,并将其写入输出管道,然后退出。
  • 同时,Parent 关闭到第 n 的输入管道两端(除了它必须保持打开的描述符),并循环返回以创建第 n+1 support> child 的 pipe ,然后是 child 。
  • 当所有子进程启动后,父进程将其 PID 写入第一个st子进程,并关闭该管道的写入端。
  • 然后它会读取第 Nth 个子级的响应,关闭管道的读取端,并打印结果。

如何验证总和不太明显,除非每个子进程也将其 PID 写入标准输出,或者父进程(知道所有子进程的 PID)计算答案来验证它。


由于完全缺乏错误检查,所以得分为零:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int N = (argc > 1) ? atoi(argv[1]) : 10;
    int c1_wr;
    int cN_rd;
    int p1[2];
    int p2[2];
    int pid_chk = getpid();

    if (N <= 0 || N >= 100)
        N = 10;

    pipe(p1);
    c1_wr = dup(p1[1]);
    printf("%d children\n", N);
    printf("Parent   = %d\n", pid_chk);

    for (int n = 0; n < N; n++)
    {
        int pid;
        pipe(p2);
        fflush(stdout);
        if ((pid = fork()) == 0)
        {
            close(p1[1]);
            close(p2[0]);
            int pid_sum;
            read(p1[0], &pid_sum, sizeof(pid_sum));
            pid_sum += getpid();
            write(p2[1], &pid_sum, sizeof(pid_sum));
            close(p1[0]);
            close(p2[1]);
            exit(0);
        }
        printf("Child %2d = %d\n", n+1, pid);
        pid_chk += pid;
        close(p1[0]);
        close(p1[1]);
        p1[0] = p2[0];
        p1[1] = p2[1];
    }

    cN_rd = p2[0];
    close(p2[1]);

    int pid_sum = getpid();
    write(c1_wr, &pid_sum, sizeof(pid_sum));
    close(c1_wr);
    read(cN_rd, &pid_sum, sizeof(pid_sum));
    close(cN_rd);
    printf("PID sum = %d\n", pid_sum);
    printf("PID chk = %d\n", pid_chk);

    return 0;
}

示例运行:

10 children
Parent   = 49686
Child  1 = 49688
Child  2 = 49689
Child  3 = 49690
Child  4 = 49691
Child  5 = 49692
Child  6 = 49693
Child  7 = 49694
Child  8 = 49695
Child  9 = 49696
Child 10 = 49697
PID sum = 546611
PID chk = 546611

如果 (a) 省略它并且 (b) 通过管道运行输出,fflush(stdout); 的用途就会变得清晰。这是必要的。

关于c - 使用 fork() 和管道的进程环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22792300/

相关文章:

linux - 什么是 makefile, 'make install' 等?

linux - 如何在 C 代码中检查目录是否在 NFS 文件系统上?

c# - 启动进程时以编程方式设置启动位置

java - 使用 Runtime.getRuntime() 在 Java 中运行命令行

linux - 为什么fork()在子进程中返回0?

c - 生命游戏实现中的段错误问题

c - 在变量不在函数参数中的情况下访问另一个函数中的变量

linux - 如何调整 linux 网络缓冲区大小

c - 我的 while 循环出现段错误

c++ - 我们可以在 C 或 C++ 中交换两个数字而不传递指针或对交换函数的引用吗?