为什么我的写入没有阻止这个管道?

时间:2018-06-06 21:56:58

标签: c linux pipe fifo

我正在编写一个Linux fifo测试程序。

我使用mkfifo mpipe创建了一个管道。程序应该为每个发送给它的参数执行一次写操作。如果没有发送参数,则它从管道执行一次读取。

这是我的代码

int main(int argc, char *argv[])
{
    if (argc > 1)
    {
       int fd = open("./mpipe", O_WRONLY);
       int i = 1;
       for (i; i < argc; i++)
       {
           int bytes = write(fd, argv[i], strlen(argv[i]) + 1);
           if (bytes <= 0)
           {
               printf("ERROR: write\n");
               close(fd);
               return 1;
           }
           printf("Wrote %d bytes: %s\n", bytes, argv[i]);
       }

       close(fd);
       return 0;
    }

    /* Else perform one read */
    char buf[64];
    int bytes = 0;

    int fd = open("./mpipe", O_RDONLY);
    bytes = read(fd, buf, 64);
    if (bytes <= 0)
    {
        printf("ERROR: read\n");
        close(fd);
        return 1;
    }
    else
    {
        printf("Read %d bytes: %s\n", bytes, buf);
    }

    close(fd);
    return 0;
}

我希望这种行为是这样的......

我打电话给./pt hello i am the deepest guy,我希望它能阻止6次读取。相反,一次读取似乎足以触发多次写入。我的输出看起来像

# Term 1 - writer
$: ./pt hello i am the deepest guy # this call blocks until a read, but then cascades.
Just wrote hello
Just wrote i
Just wrote am
Just wrote the # output ends here

# Term 2 - reader
$: ./pt
Read 6 bytes: hello

有人可以帮助解释这种奇怪的行为吗?我认为每次读取都必须与管道通信的写入相匹配。

1 个答案:

答案 0 :(得分:1)

正在发生的事情是,内核会阻止read(2)系统调用中的编写器进程,直到您有一个读取器打开它进行读取。 (一个fifo要求两端连接到进程才能工作)一旦读者完成了第一次{'h', 'e', 'l', 'l', 'o', '\0' }调用(编写器或读取器块,谁首先进行系统调用)内核传递来自编写器的所有数据对于读者来说,唤醒这两个进程(这只是接收第一个命令行参数的原因,而不是来自编写器的前16个字节,你只能从阻塞编写器中获得六个字符SIGPIPE

最后,当读者关闭fifo时,作者被write(2)信号杀死,因为没有更多读者将fifo打开。如果您在编写器进程上安装信号处理程序(或忽略信号),您将从EPIPE系统调用中收到错误,告诉您在fifo上没有阻止更多读者(read(2)阻止写入时的错误值。

请注意,这是一个功能,而不是一个错误,一种了解在您关闭并重新打开fifo之前写入不会到达任何读者的方法。

内核会阻止整个write(2)write(2)调用的fifo的inode,因此即使另一个进程在fifo上执行另一个$ pru I am the best & [1] 271 $ pru Read 2 bytes: I Wrote 2 bytes: I Wrote 3 bytes: am [1]+ Broken pipe pru I am the best <<< this is the kill to the writer process, announced by the shell. $ _ 也会被阻止,并且您可以使用&#39;我不会从第二个作者那里得到读者的数据(如果有的话)。如果你愿意,你可以尝试,启动两位作家,看看会发生什么。

suggest