我使用以下命令为 IPC 编写了以下代码pipe():
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void) {
char message_buffer[15] = "Hello World \n";
char read_buffer[15];
int fd[2];
int return_value = pipe(fd);
if (return_value < 0) {
printf("Error creating the pipe");
}
int rc = fork();
if (rc < 0) {
printf("Error forking a child");
}
if (rc > 0) {
close(fd[0]);
write(fd[1], message_buffer, 15);
close(fd[1]);
wait(NULL);
} else {
close(fd[1]);
read(fd[0], read_buffer, 15);
close(fd[0]);
printf("The Message: %s", read_buffer);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我是管道新手,我有以下问题:
我的问题似乎很愚蠢,但请帮忙回答,因为我正在为课程考试学习普通管道。
问题 1 和 2的答案位于pipe 手册页(“示例”部分):
分叉后,每个进程都会关闭管道不需要的文件描述符(请参阅管道(7))。
由于管道是单向的,因此它具有指定的端部 -读取端和写入端。如果父级将使用此管道向子级写入数据,则父级没有必要保持读取端打开。相反,如果子进程要从管道读取数据,则不需要打开写入端。
但用户@ilkkachu描述了关闭不需要的管道末端的一个更重要的原因。请查看链接的答案。
编辑:
您还问为什么父级在写入后需要关闭写入端,为什么子级在读取后需要关闭读取端。
他们不必这样做。如果两个程序要继续运行并使用管道交换数据,则它们必须保持管道打开。在一个简短的示例程序中,该程序仅演示管道的使用,并且在传输一条消息后终止,父进程和子进程可能会关闭管道文件描述符,以便在程序终止之前正确清理资源。
问题 #3 和 #4 的答案位于pipe(7) 手册页中。
你的问题#3:
由于父进程和子进程可以同时运行,如果子进程在父进程写入消息时读取消息,会发生什么情况?
子级将能够读取管道中已由父级写入的任何可用数据。根据手册页:
POSIX.1 规定小于 PIPE_BUF 字节的写入必须是原子的:输出数据作为连续序列写入管道。超过 PIPE_BUF 字节的写入可能是非原子的:内核可能会将数据与其他进程写入的数据交错。POSIX.1 要求 PIPE_BUF 至少为 512 字节。(在 Linux 上,PIPE_BUF 为 4096 字节。)
你的问题#4:
由于父级和子级可以同时运行,如果子级读取而父级尚未在管道中写入任何内容,会发生什么情况?
手册页说:
如果进程尝试从空管道读取数据,则 read(2) 将阻塞,直到数据可用。如果进程尝试写入完整管道(见下文),则 write(2) 会阻塞,直到从管道读取足够的数据以允许写入完成。
回答评论中的问题:
对于问题1和2,这意味着如果我没有关闭不需要的末端,这不会以任何方式影响程序?
它不应阻止管道工作,但会在程序使用的资源上产生一些占用空间。通过关闭管道不需要的端部,这些资源就不会被保留。
对于问题3,这意味着孩子将阅读父母正在写的内容,孩子如何知道父母已经完成了需要写的内容?
手册页说:
管道提供的通信通道是字节流:没有消息边界的概念。
这意味着管道不关心你传输的数据。它不知道“消息”意味着什么,也不知道父级是否已完成写入或想要写入更多数据。
您将需要实现自己的技术来确定什么是“完整消息”。例如,父级可以通过发送特殊字符(例如,\0或者实际上在使用管道的特定上下文中有意义的任何其他字符)来向子级表示已写入完整消息。
| 归档时间: |
|
| 查看次数: |
8086 次 |
| 最近记录: |