C语言管道读取失败求助:无法从管道读取数据
问题分析与修复
你的管道代码存在几个关键问题,导致无法正常工作:
1. 管道读写端完全搞反
pipe() 函数创建的文件描述符数组中,pip[0] 是读端,pip[1] 是写端。你现在的代码错误地向读端(pip[0])写入,从写端(pip[1])读取,这直接导致数据无法正确传输。
2. 未处理字符串终止符
read() 函数不会自动在读取的缓冲区末尾添加 \0,而你的 log() 函数用 strlen() 计算长度,会因为找不到终止符而读取到随机内存内容,甚至引发未定义行为。
3. 管道使用的额外注意事项(含fork场景)
- 单进程使用管道时:写完数据后必须关闭写端,否则
read()会一直阻塞等待更多数据(系统认为写端还可能发送数据)。 - 多进程(fork)场景:父/子进程必须关闭不需要的管道端。比如父进程写就关闭读端,子进程读就关闭写端,全部操作完成后再关闭剩余的端,否则可能导致管道无法正确触发EOF。
修正后的代码示例(单进程场景)
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define ERR -1 #define ERR_PIPE "Pipe creation failed" void logn(const char* msg) { write(1, msg, strlen(msg)); write(1, "\n", 1); } void log(const char* msg) { write(1, msg, strlen(msg)); } int main() { int pip[2]; if (pipe(pip) < 0) { logn(ERR_PIPE); return ERR; } char* buffer; // asprintf会自动分配内存,包含终止符 asprintf(&buffer, "%d, Hi\n", 11); // 向写端pip[1]写入数据 write(pip[1], buffer, strlen(buffer)); free(buffer); // 关闭写端,让read知道没有更多数据 close(pip[1]); char buffer2[32]; // 从读端pip[0]读取数据 ssize_t bytes_read = read(pip[0], buffer2, sizeof(buffer2)-1); if (bytes_read > 0) { // 添加终止符,避免strlen出错 buffer2[bytes_read] = '\0'; log(buffer2); } // 关闭读端 close(pip[0]); return 0; }
修正后的fork场景示例
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h> #define ERR -1 #define ERR_PIPE "Pipe creation failed" void logn(const char* msg) { write(1, msg, strlen(msg)); write(1, "\n", 1); } void log(const char* msg) { write(1, msg, strlen(msg)); } int main() { int pip[2]; if (pipe(pip) < 0) { logn(ERR_PIPE); return ERR; } pid_t pid = fork(); if (pid < 0) { logn("Fork failed"); return ERR; } if (pid == 0) { // 子进程:读取管道,关闭写端 close(pip[1]); char buffer2[32]; ssize_t bytes_read = read(pip[0], buffer2, sizeof(buffer2)-1); if (bytes_read > 0) { buffer2[bytes_read] = '\0'; log(buffer2); } close(pip[0]); exit(0); } else { // 父进程:写入管道,关闭读端 close(pip[0]); char* buffer; asprintf(&buffer, "%d, Hi\n", 11); write(pip[1], buffer, strlen(buffer)); free(buffer); close(pip[1]); // 等待子进程完成 wait(NULL); } return 0; }
内容的提问来源于stack exchange,提问作者CapybaraFan
相关产品推荐
相关产品推荐

