【发布时间】:2018-06-06 21:56:57
【问题描述】:
我正在编写一个小 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
有人可以帮助解释这种奇怪的行为吗?我认为就管道通信而言,每次读取都必须与写入匹配。
【问题讨论】:
-
一次读取可以从多次写入中读取数据,正如您所展示的。写入的原子性意味着来自不同进程的写入不会被交错; P1 的所有消息都将在 P2 的所有消息之前,反之亦然,受大小限制。
-
把你的
read()放在一个循环中。顺便说一句:您发送“你好”加上一个 NUL 字符(总大小 = 6) -
写入进程在读取之前不会阻塞,它会一直阻塞直到打开。即作者中的
open被阻塞,直到读者调用open。然后作者正在填充缓冲区。围绕未决调用添加一些诊断。 -
哪个 open 是第一个阻塞直到另一个(默认情况下),但是一旦两端都打开,数据就会被缓冲,并且写入器可以领先于读取器一定量这可能取决于系统; for (modern) Linux it defaults to 64kiB.
-
这就解释了为什么有时我的输出是不确定的;这只是一个竞争条件。因此,如果我修改了我的数据以预先设置传入消息的大小,那么程序可以注意这一点。