【发布时间】:2016-01-05 21:43:18
【问题描述】:
我正在做一些实验来了解命名管道。据我了解,操作系统将阻止写入命名管道的程序,直到另一个程序从命名管道读取。所以我写了两个程序,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
正如我所料,loopstart 在我使用readbyte 从 fifo 读取之前不会打印任何内容。但是,当它变得畅通时,它会多次写入“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
【问题讨论】:
-
你怎么知道
write()调用成功了?你没有检查它的返回值。 -
@Andrew Henle-我知道它至少以某种方式成功,因为
readbyte打印了所写的内容。我确实有一个带有错误检查的版本——不过,我删除了所有这些以使帖子更短。如果您认为这是问题,我可以重新添加。 -
你的循环继续的事实仅仅意味着
write()没有阻塞,而不是成功。有很大的不同。如果您不知道发生了什么并需要帮助,您发布的数据越多,您获得的帮助就越好。在这种情况下,发出循环计数器以及来自write()的返回值将比简单的“loop_start”好得多。这是一个很容易解决的问题 - 解决更难的问题将需要额外的信息。 -
我同意添加这些信息是个好主意。在这种情况下,它实际上可以隐藏问题。当我添加一个循环计数器时,我得到了一行输出,
loop 0, wrote 1 bytes。有时当我跑步时,我会得到两条线。printf使用额外参数所花费的时间最终隐藏了执行的循环数。
标签: c unix named-pipes