为什么管道不能像变量一样被覆盖?

Why can't pipes be overwritten the same way as variables?

我正在尝试用 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);

...这会 return:

0
4

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

Why isn't this phenomenon happening in pipes?

您打电话给 close() 的次数超出了应有的次数。

parent 进程在第二次写入之前关闭管道的 写入端 (即:"bar")。在第二次读取之前,child 进程正在关闭管道的 读取端 。因此,您在 child 进程中的第二次读取实际上没有从管道读取任何内容,因为传递给 read() 文件描述符 无效。请注意,由于同样的原因,parent 过程中的第二个 write() 也没有成功。

此外,已经关闭的管端正在再次关闭:parent中的读端写端 在 child.


只需删除对 close() 的那些不方便的调用,代码就会产生您所期望的结果:

#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