子进程在使用父进程将数据写入管道之前读取数据

Child process reads data before data is being written to pipe using parent

我正在使用 fork() 创建一个子进程,在父进程中我输入 5 个整数并将其保存到一个数组中。然后将此数据写入管道。然后子进程将从饼中读取数据并将其打印到屏幕上。

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define INPUT 5

int main() {
    int     fd[2];
    pid_t   childprocess;

    if((childprocess = fork()) < 0) {
        perror("Cannot fork child");
    }

    if(childprocess > 0) {
        // Parent
        int userInput[INPUT];

        close(fd[0]);

        for(int i = 0; i < INPUT; i++) {
            printf("Enter number %d: ", i+1);
            scanf("%d", &userInput[i]);
        }

        write(fd[1], userInput, sizeof(userInput) + 1);

    } else {
        // Child
        close(fd[1]);

        int parentData[INPUT];

        read(fd[0], parentData, sizeof(parentData));

        for(int i = 0; i < INPUT; i++) {
            printf("%d => %d", i+1, parentData[i]);
        }
    }

    return 0;
}

当我 运行 使用 ./a.out 的程序时,我观察到以下行为。

Enter number 1: 1 => -4731629522 => 327663 => 2005319684 => 15 => 1

管道的实现方式是否有任何错误导致了此行为?

问题是文件描述符没有被 pipe-function 初始化。当达到 read-function 时,fd[0] 可能是一个无效的文件描述符。读取 0 个字节,写入标准输出的整数正是未初始化数组 parentData 中的整数。 只需添加:

pipe(fd);

同步是如何工作的? 当使用有效的文件描述符调用 read 函数时,内核 halts/blocks 处理并等待,直到其他进程将请求的字节数 (sizeof parentData) 写入管道。然后内核从管道复制字节。这称为阻塞 IO。

注意:当写入进程stops/closes达到请求的字节数之前的文件描述符时,并不是所有的字节都被写入缓冲区。 read的return值为读取的字节数。

还有非阻塞IO。进程可以在等待数据的同时做其他事情。它通常是用一个线程实现的,它从 filedescriptor/socket(network IO) 读取(阻塞 IO)并在完成时设置一个标志。