C语言 如何准确读取管道中的消息长度?



我正在制作一个程序,孩子从父母编写的管道中读取消息。但问题是:孩子是否有可能在父母完成在管道中写完之前就开始阅读?如果是这样,子项将读取消息片段并终止。如何确保在不逐个字符读取字符并在有字符时循环读取所有消息?

这是我的代码:

#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("%sn", msg);
exit(0);
default:
close(p[0]);
strcpy(msg, "Very long text ...");
write(p[1], &msg, TEXT_LENGTH);
wait(NULL);
}
return 0;
}

现在它可以工作,但是如果文本很长,父母是否有时间在孩子进入阅读之前写信?

从你调用fork的那一刻起,你可以确定写在管道上的所有内容都将被子进程读取:

  • 如果父级写入了某些内容,而子级没有立即读取它,它将保留在管道缓冲区中,直到子级读取为止。
  • 如果孩子在父母开始写作之前开始阅读,那么孩子的read将阻塞,直到有东西要读。

您可能希望在父级中写入数据后close(p[1]),以便子级可以正确识别数据的末尾。在您的特定情况下,这不是问题,因为您写入的数据量固定并读取完全相同的数据量,但一般来说,最好在写入管道后关闭管道。

真的没什么好担心的。如果你有一个很长的字符串,唯一会更好的事情是读取和写入块,并在子块中分别处理每个块,这样你的程序就不会使用太多内存来保留它不需要的东西。

另外,旁注:当您使用字符串文字"like this"时,您不必添加 NUL 终止符,它是自动添加的。

孩子

是否有可能在父母完成写作之前就开始在管道中阅读?

这不是一个问题。read(2)调用阻止,直到有要读取的内容,除非您将文件描述符标记为非阻塞。

如何确保在不逐个字符读取字符并在有字符时循环读取所有消息?

问题是管道不理解"消息"是什么,或者它的开始或结束;它只是从一端传递到另一端的字节流。有关详细信息,请阅读pipe(7)

如果你有任何"开始"、"结束"、"长度"标记,那么你需要构建/解构自己。您始终可以要求read(2)更多,如果返回的内容低于要求的内容,您可以得出结论,这就是全部(同时检查返回值并errno了解其确切原因:文件结束,I/O错误等)。

最新更新