为什么在没有人阅读之后继续写入命名管道?

时间:2016-01-05 21:43:19

标签: c unix named-pipes

我正在做一些实验来了解命名管道。根据我的理解,操作系统将阻止写入命名管道的程序,直到另一个程序从命名管道读取为止。所以我写了两个程序startloopreadbytestartloop创建一个fifo,并在每次读取客户端(readbyte)时不断写入:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>

int main(int argc, char *argv[]) {
    const char num = 123;
    mkfifo("fifo", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    int fd = open("fifo", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    while (1) {
        printf("loop_start\n");
        write(fd, &num, sizeof(num));
    }
    close(fd);
    return 0;
}

readbyte在运行时读取fifo中的一个字节:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char *argv[]) {
    char num;
    int fd;
    if ((fd = open(argv[1], O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) {
        perror("Cannot open input file\n"); exit(1);
    }

    read(fd, &num, sizeof(num));
    printf("%d\n", num);
    close(fd);
    return 0;
}

readbyte在&#34; fifo&#34;

上运行时按预期打印数字
hostname:dir username$ ./readbyte fifo 
65

正如我所料,loopstart在我使用readbyte读取fifo之前不会打印任何内容。然而,当它被解锁时,它会写入&#34; fifo&#34;几次而不是立即被停职。这是为什么?

hostname:dir username$ ./startloop
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start
loop_start

2 个答案:

答案 0 :(得分:3)

“我的理解是操作系统将阻止写入命名管道的程序,直到另一个程序从命名管道读取。”

这种理解是不正确的。除非管道/ fifo已满,否则write不会阻止。来自pipe manul

  

管道容量有限。如果管道已满,则写入(2)   将阻塞或失败,具体取决于是否设置了O_NONBLOCK标志   (见下文)。

至于为什么第一个write似乎阻止了 - 实际上并没有。是open阻止。来自fifo manaul

  

必须在数据之前打开FIFO(读取和写入)   可以通过。通常,打开FIFO块直到另一端   也开了。

更新:实际上上面的第一个write是正确的。但可能有更多的解释。一旦readbyte程序关闭了fifo,后续的write调用应该开始失败。

答案 1 :(得分:1)

测试写入结果

 while (1) {
        printf("loop_start\n");
     int ret =  write(fd, &num, sizeof(num));
     if(ret == -1)
     {
        perror("error writing to fifo");
        exit(1);
     }
    }