为什么在没有人阅读后继续写入命名管道?
Why does writing to a named pipe continue after no one is reading?
我正在做一些实验来了解命名管道。据我了解,OS 将阻止写入命名管道的程序,直到另一个程序从命名管道读取为止。所以我写了两个程序,startloop
和 readbyte
。 startloop
创建一个 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
在 "fifo":
上 运行 时按预期打印数字
hostname:dir username$ ./readbyte fifo
65
如我所料,在我使用 readbyte
从 fifo 读取之前,loopstart
不会打印任何内容。但是,当它解除阻塞时,它会多次写入 "fifo" 而不是立即被挂起。这是为什么?
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
测试写入结果
while (1) {
printf("loop_start\n");
int ret = write(fd, &num, sizeof(num));
if(ret == -1)
{
perror("error writing to fifo");
exit(1);
}
}
"It's my understanding that the OS will block a program that writes to a named pipe until another program reads from the named pipe."
这种理解是不正确的。 write
不会阻塞,除非 pipe/fifo 已满。来自 pipe manul:
A pipe has a limited capacity. If the pipe is full, then a write(2)
will block or fail, depending on whether the O_NONBLOCK flag is set
(see below).
至于为什么第一个 write
看起来是阻塞的——实际上并没有。阻塞的是 open
。来自 fifo manaul:
The FIFO must be opened on both ends (reading and writing) before data
can be passed. Normally, opening the FIFO blocks until the other end
is opened also.
更新:实际上上述第一个 write
是正确的。但可能还有更多需要解释的地方。 readbyte
程序关闭 fifo 后,后续 write
调用应该开始失败。
我正在做一些实验来了解命名管道。据我了解,OS 将阻止写入命名管道的程序,直到另一个程序从命名管道读取为止。所以我写了两个程序,startloop
和 readbyte
。 startloop
创建一个 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
当运行:
#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
在 "fifo":
hostname:dir username$ ./readbyte fifo
65
如我所料,在我使用 readbyte
从 fifo 读取之前,loopstart
不会打印任何内容。但是,当它解除阻塞时,它会多次写入 "fifo" 而不是立即被挂起。这是为什么?
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
测试写入结果
while (1) {
printf("loop_start\n");
int ret = write(fd, &num, sizeof(num));
if(ret == -1)
{
perror("error writing to fifo");
exit(1);
}
}
"It's my understanding that the OS will block a program that writes to a named pipe until another program reads from the named pipe."
这种理解是不正确的。 write
不会阻塞,除非 pipe/fifo 已满。来自 pipe manul:
A pipe has a limited capacity. If the pipe is full, then a write(2) will block or fail, depending on whether the O_NONBLOCK flag is set (see below).
至于为什么第一个 write
看起来是阻塞的——实际上并没有。阻塞的是 open
。来自 fifo manaul:
The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.
更新:实际上上述第一个 write
是正确的。但可能还有更多需要解释的地方。 readbyte
程序关闭 fifo 后,后续 write
调用应该开始失败。