【发布时间】:2018-10-29 11:06:04
【问题描述】:
我正在制作一个程序,其中孩子从父母编写的管道中读取消息。但问题是:有没有可能孩子在父母完成写入之前就开始在管道中阅读?如果是这样,孩子将阅读消息的片段并终止。如何确保在不逐个字符读取字符并在有字符时循环读取所有消息的情况下读取所有消息?
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#define TEXT_LENGTH 20
int main(void) {
int p[2];
char msg[TEXT_LENGTH];
if (pipe(p) == -1) {
perror("Error");
exit(1);
}
switch (fork()) {
case -1:
perror("Error");
exit(1);
case 0:
close(p[1]);
read(p[0], &msg, TEXT_LENGTH);
printf("%s\n", msg);
exit(0);
default:
close(p[0]);
strcpy(msg, "Very long text ...\0");
write(p[1], &msg, TEXT_LENGTH);
wait(NULL);
}
return 0;
}
现在可以了,但是如果文本很长,在孩子进入阅读之前,父母有时间写吗?
【问题讨论】:
-
如果没有什么要阅读的,阅读器会block。并且:读写都是原子的(至少,最多一个缓冲区长度)
-
我认为管道在标记为关闭之前不会让您读取它们。
-
查找 TLV(类型、长度、值)编码。用它。如果父母向孩子发送多条消息(不是给孩子的一条消息,来自孩子的单一响应——你可以更简单地做到这一点),那么 TLV 上的一些变体是必要的,这样你就知道要读取多少数据。在紧要关头,您可以为每条消息使用“结束标记”,但需要小心。
-
如果您的消息小于管道缓冲区的大小(介于 4 KiB 和 64 KiB 之间),那么您可以原子地编写完整的消息。如果它们比缓冲区长,则必须进行多次读取才能获取所有数据。如果消息很短并且协议是同步的(所以在孩子响应之前的消息之前,父母不会向孩子发送新消息),那么你可以让孩子阅读大块,并且知道它会获取全部信息。您的代码显示了一个写入/读取周期——您的孩子可以简单地读取到 EOF(如果父级关闭管道)。