【问题标题】:Multiple children reading from/writing to a single parent多个孩子从单亲读/写给单亲
【发布时间】:2013-03-09 17:04:00
【问题描述】:

这里我有一个程序,其中一个父进程创建了几个子进程,通过 他们每个人都有一个不同的整数。然后每个子进程将读取的整数写回父进程,父进程将结果打印到标准输出:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define R 0
#define W 1

void run_child(int in, int out){
    int r;
    int it;
    while((r = read(in, &it, sizeof(it))) != 0){
        if(r == -1){
            perror("read");
            exit(1);
        }
        //word[r] = '\0';
        int w = write(out, &it, sizeof(it));
        if(w == -1){
            perror("write");
            exit(1);
        }
        if(close(out) == -1){
            perror("close");
            exit(1);
        }
    }
}
int main(int argc, char **argv) {

    // Process fan

    int i;
    int n;
    int num_kids;
    int from_parent[2];
    int to_parent[2];


    if(argc != 2) {
        fprintf(stderr, "Usage: fan_write <numkids>\n");
        exit(1);
    }

    num_kids = atoi(argv[1]);
    int status;

    char word[32];
    for(i = 0; i < num_kids; i++) {
        if(pipe(from_parent) == -1){
            perror("pipe");
            exit(1);
        }
        if(pipe(to_parent) == -1){
            perror("pipe");
            exit(1);
        }
        int g = i;
        write(from_parent[W], &g, sizeof(int));

        n = fork();
        if(n < 0) {
            perror("fork");
            exit(1);
        }
        if(n == 0){
            if(close(from_parent[W]) == -1){
                perror("close");
                exit(1);
            }
            if(close(to_parent[R]) == -1){
                perror("close");
                exit(1);
            }
            dup2(from_parent[R], STDIN_FILENO);
            if(close(from_parent[R]) == -1){
                perror("close");
                exit(1);
            }
            run_child(STDIN_FILENO, to_parent[W]);
            close(to_parent[W]);
            exit(0);
        }

        if(close(from_parent[R]) == -1){
            perror("close");
            exit(1);
        }
        if(close(to_parent[W]) == -1){
            perror("close");
            exit(1);
        }

        if(close(from_parent[W]) == -1){
            perror("close");
            exit(1);
        }

        for(i=0;i<num_kids;i++){
            int read_int;
            int r = read(to_parent[R], &read_int, sizeof(int));
            printf("read %d bytes\n", r);
            if(r == -1){
                perror("read");
                exit(1);
            }
            printf("%d\n", read_int);
        }
    }
    for(i = 0; i < num_kids; i++){
        wait(&status);
    }

    return 0;
}

使用 num_kids = 4 我希望程序每次读取 4 个字节并打印 不同的整数。但是,运行时它在一次迭代中读取 4 个字节,然后读取 在以下迭代中为 0 个字节,并一遍又一遍地打印相同的整数。我不知道如何解决它。

编辑:已解决!提示:对管道使用文件描述符矩阵。

【问题讨论】:

    标签: c process fork pipe


    【解决方案1】:

    你有错误的概念来循环读取所有num_kids子进程的数字,你每次都从单个子进程和每个子进程中循环读取:

       for(i=0;i<num_kids;i++){ 
            int read_int;
            int r = read(to_parent[R], &read_int, sizeof(int));
            printf("read %d bytes\n", r);
            if(r == -1){
                perror("read");
                exit(1);
            }
            printf("%d\n", read_int);
        }
    

    是否也为每个孩子(包括父母)运行代码,因为您在子/父进程中无条件地运行此循环。但是父母可以从单个孩子那里读到你第一次获得4字节然后0的原因。因为孩子一次返回一个数字。从您的代码中删除上面的 for 循环,并按照我在下面的建议进行操作:

    你应该喜欢(阅读 cmets):

    if(n == 0){
       //child
    }
    else{ 
      // read in parent without loop
    }
    

    所以正确的方法是:

        if(n == 0){//child
            if(close(from_parent[W]) == -1){
                perror("close");
                exit(1);
            }
            if(close(to_parent[R]) == -1){
                perror("close");
                exit(1);
            }
            dup2(from_parent[R], STDIN_FILENO);
            if(close(from_parent[R]) == -1){
                perror("close");
                exit(1);
            }
            run_child(STDIN_FILENO, to_parent[W]);
            close(to_parent[W]);
            exit(0);
        }
        else{ // parent
           write(from_parent[W], &g, sizeof(int)); 
           int read_int;
           int r = read(to_parent[R], &read_int, sizeof(int));
            printf("read %d bytes\n", r);
            if(r == -1){
                perror("read");
                exit(1);
            }
            printf("%d\n", read_int);
        }
    

    它的工作方式如下:

    :~$ ./a.out  4
    read 4 bytes
    0
    read 4 bytes
    1
    read 4 bytes
    2
    read 4 bytes
    3
    

    【讨论】:

    • 但我只需要 4 个字节。发送给每个孩子的数字在 [0...3] 范围内。我想我错过了什么。
    • 您的意思是等待应答还是呼叫等待有问题?
    • @user1472346 好的阅读答案,如果你想要完整的代码,请告诉我
    • @user1472346 好:) 我可以给你很好的链接来轻松学习它
    • 那会很有帮助!再次感谢!
    【解决方案2】:
    if (n == 0) { //child
        if(close(from_parent[W]) == -1) {
            perror("close");
            exit(1);
        }
        if(close(to_parent[R]) == -1) {
            perror("close");
            exit(1);
        }
        run_child(from_parent[R], to_parent[W]);
        close(from_parent[R]);   // ignore checking return code here!
        close(to_parent[W]);     // ignore checking return code here!
        exit(0);
    }
    
    // And this is what run_child looks like
    void run_child(int in, int out){
        int r;
        int it;
        while((r = read(in, &it, sizeof(it))) != 0){
            if(r == -1){
                perror("read");
                exit(1);
            }
    
            int w = write(out, &it, sizeof(it));
            if(w == -1){
                perror("write");
                exit(1);
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      我混淆了 aswers 代码,这是最终结果.. 一切顺利

      #include <stdio.h>
      #include <unistd.h>
      #include <stdlib.h>
      #include <sys/wait.h>
      #define R 0
      #define W 1
      
      void run_child(int in, int out){
          int r;
          int it;
          while((r = read(in, &it, sizeof(it))) != 0){
              if(r == -1){
                  perror("read");
                  exit(1);
              }
      
              int w = write(out, &it, sizeof(it));
              //perror("write:");
              //close(out) ;
      
              exit(1);
      
          }
      }
      int main(int argc, char **argv) {
      
          // Process fan
      
          int i;
          int n;
          int num_kids;
          int from_parent[2];
          int to_parent[2];
      
      
          if(argc != 2) {
              fprintf(stderr, "Usage: fan_write <numkids>\n");
              exit(1);
          }
      
          num_kids = atoi(argv[1]);
          int status;
      
          char word[32];
          for(i = 0; i < num_kids; i++) {
              if(pipe(from_parent) == -1){
                  perror("pipe");
                  exit(1);
              }
              if(pipe(to_parent) == -1){
                  perror("pipe");
                  exit(1);
              }
              int g = i;
              write(from_parent[W], &g, sizeof(int));
      
              n = fork();
              if(n < 0) {
                  perror("fork");
                  exit(1);
              }
      
              if(n == 0){//child
                  if(close(from_parent[W]) == -1){
                      perror("close");
                      exit(1);
                  }
                  if(close(to_parent[R]) == -1){
                      perror("close");
                      exit(1);
                  }
                  run_child(from_parent[R], to_parent[W]);
      
                  if(close(from_parent[R]) == -1){
                      perror("close");
                      exit(1);
                  }
                  if(close(to_parent[W]) == -1){
                      perror("close");
                      exit(1);
                  }
      
                  exit(0);
              }
              else{ // parent
                 write(from_parent[W], &g, sizeof(int)); 
                 int read_int;
                 int r = read(to_parent[R], &read_int, sizeof(int));
                  printf("read %d bytes\n", r);
                  if(r == -1){
                      perror("read");
                      exit(1);
                  }
                  printf("%d\n", read_int);
              }
      
          }
      
      
          for(i = 0; i < num_kids; i++){
              wait(&status);
          }
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 2019-11-07
        • 2021-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-04
        • 1970-01-01
        • 2020-04-29
        相关资源
        最近更新 更多