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

时间:2019-05-11 14:06:47

标签: c pipe fork file-descriptor

我正在使用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

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

1 个答案:

答案 0 :(得分:3)

问题在于文件描述符未通过管道功能初始化。达到读取功能后,fd[0]可能是无效的文件描述符。读取0字节,写入stdout的整数就是未初始化数组parentData中的整数。 只需添加:

pipe(fd);

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

注意:当写入过程在达到请求的字节数之前停止/关闭filedescriptor时,并非所有字节都被写入缓冲区。 read的返回值是读取的字节数。

还有非阻塞IO。该过程可以在等待数据时执行其他操作。它通常由线程实现,该线程从文件描述符/套接字(网络IO)读取(带有阻塞IO)并在完成时设置标志。