操作系统课程中管道未使用端关闭的代码疑问
Hey there! Let's walk through your pipe code, fill in the missing parts of the reader process, and clear up key concepts that often trip people up when working with Unix pipes.
First, let's look at the complete, corrected version of your code to make things concrete:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { int fd[2]; // 创建管道,fd[0]是读端,fd[1]是写端 pipe(fd); int status; int pid = fork(); if (pid == 0) { // 子进程:写进程 srand(123); int arr[3] = {1, 2, 3}; close(fd[0]); // 关闭未使用的读端——必须做! for (int i = 0; i < 3; i++) { write(fd[1], &arr[i], sizeof(int)); } close(fd[1]); // 写入完成后关闭写端,触发读端的EOF exit(EXIT_SUCCESS); } else { // 父进程:读进程 int arr[10]; int i = 0; ssize_t bytes_read; close(fd[1]); // 关闭父进程未使用的写端——这是很多人漏掉的关键步骤! // 循环读取直到遇到EOF(read返回0)或错误 while ((bytes_read = read(fd[0], &arr[i], sizeof(int))) > 0) { printf("Read value: %d\n", arr[i]); i++; } // 处理read的错误情况 if (bytes_read == -1) { perror("Failed to read from pipe"); exit(EXIT_FAILURE); } close(fd[0]); wait(&status); // 等待子进程结束,回收资源避免僵尸进程 } return 0; }
Key Questions & Explanations
Let's break down the critical parts you might be confused about:
Why do we close unused pipe ends?
Pipes are structured to be bidirectional, but we're using it unidirectionally here (child writes, parent reads). If we don't close the unused ends:- For the child: Leaving
fd[0]open means the pipe's read end is still held open by the child, so the parent might never get an EOF signal even after the child finishes writing. - For the parent: Leaving
fd[1]open is even more important! The kernel won't send EOF to the parent'sread()call until all write ends of the pipe are closed. If the parent keepsfd[1]open,read()will block forever waiting for more data, even after the child closes itsfd[1].
- For the child: Leaving
How does the read process know when to stop?
When the child closesfd[1](and the parent has already closed its ownfd[1]), the nextread()call onfd[0]will return0—this is the EOF (end-of-file) signal, telling the parent there's no more data to read. That's why we loop whilebytes_read > 0.What about waiting for the child process?
Usingwait(&status)ensures the parent waits for the child to exit completely, which cleans up the child's process resources and prevents it from becoming a "zombie process" (a defunct process that lingers in the system).
Common Mistakes to Avoid
- Forgetting to close unused pipe ends (especially the parent's write end) leads to infinite blocking on
read(). - Not checking the return value of
read()—it can return-1on error (like if the pipe is broken), so always handle that case. - Skipping
wait()leaves zombie processes cluttering your system.
内容的提问来源于stack exchange,提问作者Arka Pal

