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