我试图用C语言编写一个简单的程序,其中一些内容通过管道传递给子进程两次,每次使用不同的值:

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

#define READ  0
#define WRITE 1

int main(){
    int myPipe[2];
    if (pipe(myPipe) < 0) {
        fprintf(stderr,"Pipe Error!");
        return -1;
    }
    pid_t pid = fork();
    if (pid < 0)
        perror("Error forking!");
    else if(pid > 0){
    // Master
        char var[4];

        // Sends the first value.
        sprintf(var, "foo");
        close(myPipe[READ]);
        write(myPipe[WRITE], var, sizeof(var));
        close(myPipe[WRITE]);

        // Sends the second value.
        sprintf(var, "bar");
        close(myPipe[READ]);
        write(myPipe[WRITE], var, sizeof(var));
        close(myPipe[WRITE]);

        wait(NULL);
        return 0;
    }
    else if (pid == 0){ // Child
        char received[4];

        // Reads the first value.
        close(myPipe[WRITE]);
        read(myPipe[READ], received, sizeof(received));
        close(myPipe[READ]);
        printf("I have received the following value: %s\n", received);

        // Reads the second value.
        close(myPipe[WRITE]);
        read(myPipe[READ], received, sizeof(received));
        close(myPipe[READ]);
        printf("I have received the following value: %s\n", received);
        return 0;
    }
}

不过,输出似乎不是预期的,因为变量received从不改变其值:
I have received the following value: foo
I have received the following value: foo

…当所需输出为:
I have received the following value: foo
I have received the following value: bar

我不明白为什么会发生这种情况,因为我认为-可能是错误的-管道在每次使用时都会被覆盖,就像您可以执行的那样:
int i = 0;
printf("%i\n", i);
i = 4;
printf("%i", i);

……它将返回:
0
4

为什么这种现象不发生在管道中?

最佳答案

为什么这种现象不发生在管道中?
你打电话的次数比你应该打的多。
父进程在第二次写入之前关闭管道的写入端(即:“bar”)。子进程在第二次读取之前关闭管道的读取端。因此,子进程中的第二次读取实际上没有从管道中读取任何内容,因为传递给close()的文件描述符无效。注意,父进程中的第二个read()也没有成功,原因相同。
此外,已关闭的管道端将再次关闭:父级中的读取端和子级中的写入端。
通过删除那些对write()不方便的调用,代码将产生您所期望的结果:

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

#define READ  0
#define WRITE 1

int main(){
    int myPipe[2];
    if (pipe(myPipe) < 0) {
        fprintf(stderr,"Pipe Error!");
        return -1;
    }
    pid_t pid = fork();
    if (pid < 0)
        perror("Error forking!");
    else if(pid > 0){
    // Master
        char var[4];

        // Sends the first value.
        sprintf(var, "foo");
        close(myPipe[READ]);
        write(myPipe[WRITE], var, sizeof(var));

        // Sends the second value.
        sprintf(var, "bar");
        write(myPipe[WRITE], var, sizeof(var));
        close(myPipe[WRITE]);

        wait(NULL);
        return 0;
    }
    else if (pid == 0){ // Child
        char received[4];

        // Reads the first value.
        close(myPipe[WRITE]);
        read(myPipe[READ], received, sizeof(received));
        printf("I have received the following value: %s\n", received);

        // Reads the second value.
        read(myPipe[READ], received, sizeof(received));
        printf("I have received the following value: %s\n", received);
        return 0;
    }

  return 0;
}

也就是说,输出是:
I have received the following value: foo
I have received the following value: bar

10-06 04:09
查看更多