C 如何用叉子和管子制作工艺环?

C 如何用叉子和管子制作工艺环?,c,pipe,fork,child-process,C,Pipe,Fork,Child Process,目前我正在学习C,我想用叉子和管子做一个由n个孩子组成的环过程,其中n是一个数字,在参数中输入,每个孩子可以与下一个孩子在一个方向上进行交流 我尝试在每个孩子向下一个孩子发送其pid时执行此操作,但我没有得到我想要的,例如,如果我创建3个孩子: PID:1,循环中的i:0,接收到的i:0 PID:2,循环中的i:1,接收到的i:0 PID:3,循环中的i:2,接收到的i:0 但我应该得到: PID:1,循环中的i:0,接收到的i:3 PID:2,循环中的i:1,接收到的i:1 PID:3,循环中

目前我正在学习C,我想用叉子和管子做一个由n个孩子组成的过程,其中n是一个数字,在参数中输入,每个孩子可以与下一个孩子在一个方向上进行交流 我尝试在每个孩子向下一个孩子发送其pid时执行此操作,但我没有得到我想要的,例如,如果我创建3个孩子:

  • PID:1,循环中的i:0,接收到的i:0
  • PID:2,循环中的i:1,接收到的i:0
  • PID:3,循环中的i:2,接收到的i:0
  • 但我应该得到:

  • PID:1,循环中的i:0,接收到的i:3
  • PID:2,循环中的i:1,接收到的i:1
  • PID:3,循环中的i:2,接收到的i:2
  • 有时我会从一个随机的子对象到另一个随机的子对象接收一个值。这是我的代码,我对循环中的多个管道不太适应

    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include <fcntl.h>              
    #include <unistd.h>
    
    int main(int argc, const char * argv[]) {
        if(argc != 2) {
            fprintf(stderr, "Usage : %s <integer> [> 2]\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        int number_process = atoi(argv[1]);
        if(number_process < 2) {
            fprintf(stderr, "Usage : %s <integer> [> 2]\n", argv[0]);
            exit(EXIT_FAILURE);
        }
    
        printf("Création de %d processus pour une élection : \n", number_process);
        int i = 0, j = 0, k = 0;
        int * t = (int *) malloc((2 * number_process) * sizeof(int));
    
        for(k = 0; k < number_process; k++) {
            pipe(&t[2*i]);
        }
    
        for(i = 0; i < number_process; i++) {
            if(fork() == 0) {
                for(j = 0; j < number_process*2; j++) {
                    if(j != 2*i && j != ((2*i+3)%(number_process*2))) {
                        close(t[j]);
                    }
                }
                close(t[(2*i+1)%(number_process*2)]);
                close(t[((2*i+2)%(number_process*2))]);
    
                int pid = (int) getpid();
                write(t[(2*i+3)%(number_process*2)], &pid, sizeof(int));
    
                int in = 0;
                read(t[i*2], &in, sizeof(int));
                printf("%d : %d\n", in, getpid()); 
    
                exit(EXIT_SUCCESS);
            }
        }
        return (EXIT_SUCCESS);
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    int main(int argc,const char*argv[]{
    如果(argc!=2){
    fprintf(stderr,“用法:%s[>2]\n”,argv[0]);
    退出(退出失败);
    }
    int number_进程=atoi(argv[1]);
    if(进程数<2){
    fprintf(stderr,“用法:%s[>2]\n”,argv[0]);
    退出(退出失败);
    }
    printf(“工艺选择:\n”,工艺编号);
    int i=0,j=0,k=0;
    int*t=(int*)malloc((2*number_进程)*sizeof(int));
    对于(k=0;k
    以下是我在程序中发现的问题:

  • 无错误检查。如果不进行错误检查,则很难找到其他错误。请注意,如果发生错误,
    read()
    将返回否定结果。在这种情况下,您可能会从
    read()
    获得
    EBADF

  • 添加错误检查后,您将调查
    EBADF
    错误的来源,并注意管道未正确初始化。这是由于管线
    管道(&t[2*i])
    应该使用
    k
    而不是
    i
    。找到此错误的另一种方法是使用地址消毒剂或Valgrind,这两种方法都可以立即找到错误(无需更改代码)。在循环中对循环变量进行范围界定也会立即发现此问题,因此使用
    for(int i=0;…)
    而不是
    int i;对于(i=;…)

  • 循环结束后,对已关闭的文件调用两次
    close()
    函数。然而,这个错误是无害的

  • 父进程应等待其子进程退出,并且还应首先关闭管道

  • 程序依靠行缓冲来正确工作。一个好的解决方案是在调用
    fork()
    之前执行
    fflush(stdout)

  • 以下是一个更新版本,其中包含注释:

    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include <fcntl.h>              
    #include <unistd.h>
    
    void usage(const char *prog) {
        fprintf(stderr, "Usage : %s <integer> [> 2]\n", prog);
        exit(1);
    }
    
    int main(int argc, const char * argv[]) {
        if(argc != 2) {
            usage(argv[0]);
        }
    
        int number_process = atoi(argv[1]);
        if(number_process < 2) {
            usage(argv[0]);
        }
    
        printf("Création de %d processus pour une élection : \n", number_process);
        // Flush stdout before fork.
        fflush(stdout);
    
        // Do not cast the result of malloc
        // Use sizeof(*pipes) instead of sizeof(int)
        // Prefer descriptive variable names
        int *pipes = malloc((2 * number_process) * sizeof(*pipes));
        if (!pipes) {
            perror("malloc");
            exit(1);
        }
    
        // Scope loop variables in the loop
        for (int i = 0; i < number_process; i++) {
            int r = pipe(&pipes[2*i]);
            if (r == -1) {
                perror("pipe");
                exit(1);
            }
        }
    
        for (int i = 0; i < number_process; i++) {
            pid_t pid = fork();
            if (pid == -1) {
                perror("fork");
                exit(1);
            }
            if (pid == 0) {
                // Let's avoid copy/pasting 2*i and (2*i+3)%(number_process*2)
                // everywhere, which is hard to read
                int infd = pipes[2*i];
                int outfd = pipes[(2*i+3)%(number_process*2)];
                for (int j = 0; j < number_process*2; j++) {
                    if (pipes[j] != infd && pipes[j] != outfd) {
                        close(pipes[j]);
                    }
                }
    
                int self = getpid();
                ssize_t amt;
                amt = write(outfd, &self, sizeof(int));
                if (amt == -1) {
                    perror("write");
                    exit(1);
                }
    
                int in;
                ssize_t r = read(pipes[i*2], &in, sizeof(int));
                if (r == -1) {
                    perror("read");
                    exit(1);
                }
                printf("%d : %d\n", in, (int)getpid()); 
    
                exit(0);
            }
        }
        // Close pipes and wait for children to finish
        for (int i = 0; i < number_process * 2; i++) {
            close(pipes[i]);
        }
        for (int i = 0; i < number_process; i++) {
            wait(NULL);
        }
    
        // Return at end of main() is implicitly "return 0".
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    无效用法(常量字符*prog){
    fprintf(标准,“用法:%s[>2]\n”,程序);
    出口(1);
    }
    int main(int argc,const char*argv[]{
    如果(argc!=2){
    用法(argv[0]);
    }
    int number_进程=atoi(argv[1]);
    if(进程数<2){
    用法(argv[0]);
    }
    printf(“工艺选择:\n”,工艺编号);
    //在叉子前冲洗标准液。
    fflush(stdout);
    //不要强制转换malloc的结果
    //使用sizeof(*管道)而不是sizeof(int)
    //更喜欢描述性变量名
    int*pipes=malloc((2*工艺编号)*尺寸(*管道));
    如果(!管道){
    佩罗尔(“马洛克”);
    出口(1);
    }
    //循环中的作用域循环变量
    for(int i=0;i
    你怎么知道代码是错的?我用printf测试了它,其中I,curre