如何修复C语言中子进程管道通信日志器无输出问题?
管道通信日志器的子进程无输出问题修复
问题场景
尝试用C语言实现管道通信的日志器,父进程发送消息,子进程接收并打印,但运行时仅能看到父进程的printf输出,子进程无任何输出。调试发现子进程卡在第一个read语句,父进程写入操作无报错。
原代码
main函数
int main(void){ spawn_logger(); char wmsg[] = "Greetings"; send_message(wmsg); strcpy(wmsg, "Hello"); send_message(wmsg); kill_child(); return 0; }
spawn_logger函数
// global vars pid_t pid; int fd[2]; int spawn_logger() { if (pipe(fd) == -1) { printf("Pipe failed\n"); return -1; } pid = fork(); if (pid < 0) { // fork error printf("fork failed"); return -1; } if (pid > 0) { // parent process close(fd[READ_END]); return 0; // return to main } // child process // spawn the receiver process log_message(); // the receiver process will never reach this point return 0; }
send_message函数
int send_message(char message[]){ // do something with the message // e.g. write in a file printf("Message by parent sent: %s \n", message); // write the message to logger process int n = strlen(message) + 1; write(fd[WRITE_END], &n, sizeof(int)); write(fd[WRITE_END], &message, sizeof(char) * strlen(message)); return 0; }
log_message和kill_child函数
// global vars extern pid_t pid; extern int fd[2]; int log_message(){ //child process // will read from the pipe every time the parent process writes to it close(fd[WRITE_END]); int n; char *message; // read messages until parent process closes the pipe while (read(fd[READ_END], &n, sizeof(int)) > 0) { message = malloc(sizeof(char) * n); read(fd[READ_END], &message, sizeof(char) * n); printf("Message by logger received: %s \n", message); } close(fd[READ_END]); exit(0); } int kill_child(){ close(fd[WRITE_END]); kill(pid, SIGKILL); return 0; }
问题分析与修复
1. 管道读写的指针传递错误(核心问题)
- send_message函数:
write(fd[WRITE_END], &message, sizeof(char)*strlen(message));错误传递了数组指针的地址,而非数组内容的首地址。数组名message本身就是首地址,且需要写入包含\0的完整字符串,应改为write(fd[WRITE_END], message, n);。 - log_message函数:
read(fd[READ_END], &message, sizeof(char)*n);错误将数据写入指针变量message的地址,而非malloc分配的内存区域,应改为read(fd[READ_END], message, n);。
2. 子进程stdout缓冲问题
子进程的printf输出可能因全缓冲机制未即时刷新,导致看不到输出,需在printf后调用fflush(stdout);强制刷新缓冲区。
3. 内存泄漏问题
log_message中malloc的内存未释放,需在打印后调用free(message);避免泄漏。
4. 子进程终止逻辑优化
父进程关闭管道写端后,子进程的read会返回0,自动退出循环并正常终止,无需调用kill,可改为等待子进程正常退出。
修复后的代码
修复后的send_message
int send_message(char message[]){ printf("Message by parent sent: %s \n", message); int n = strlen(message) + 1; write(fd[WRITE_END], &n, sizeof(int)); // 传递数组首地址,写入包含\0的完整字符串 write(fd[WRITE_END], message, n); return 0; }
修复后的log_message
int log_message(){ close(fd[WRITE_END]); int n; char *message; while (read(fd[READ_END], &n, sizeof(int)) > 0) { message = malloc(sizeof(char) * n); // 读取到malloc分配的内存区域 read(fd[READ_END], message, n); printf("Message by logger received: %s \n", message); // 强制刷新输出缓冲区 fflush(stdout); // 释放内存避免泄漏 free(message); } close(fd[READ_END]); exit(0); }
优化后的kill_child
int kill_child(){ close(fd[WRITE_END]); // 等待子进程正常退出 waitpid(pid, NULL, 0); return 0; }
验证效果
修复后运行程序,会看到父进程和子进程的输出依次打印:
Message by parent sent: Greetings Message by logger received: Greetings Message by parent sent: Hello Message by logger received: Hello
内容的提问来源于stack exchange,提问作者curioso
相关产品推荐
相关产品推荐

