4

ここに、親プロセスが複数の子プロセスを作成し、それぞれに個別の整数を渡すプログラムがあります。次に、各子プロセスは、読み取った整数を親プロセスに書き戻します。親プロセスは、結果を標準出力に出力します。

#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バイトを読み取り、個別の整数を出力することを期待します。ただし、実行すると、1回の反復で4バイトを読み取り、次の反復で0バイトを読み取り、同じ整数を繰り返し出力します。修正方法がわかりません。

編集:解決しました!ヒント:パイプのファイル記述子のマトリックスを使用してください。

4

3 に答える 3

2

ループ内のすべての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ループをコードから削除し、以下で提案しているようにします。

あなたは好きなことをするべきです(コメントを読んでください):

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
于 2013-03-20T15:31:16.927 に答える
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]);
    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);
        }
    }
}
于 2013-03-21T02:46:57.097 に答える
0

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;
}
于 2014-05-15T07:58:22.317 に答える