两个C程序间管道通信无输出问题求解
问题原因与解决方案
你的程序陷入死锁,核心原因是管道写端未及时关闭,导致子进程的read调用一直阻塞等待更多数据,同时父进程在等待子进程返回结果,双方互相卡住。
具体问题点
- 父进程发送完所有数据后,没有关闭
pipe_to_loop[1](管道写端)。子进程调用read(0, str1, sizeof(str1))尝试读取100字节,但父进程只发送了16字节(两个带终止符的字符串+一个int),且写端仍处于打开状态,子进程会一直等待更多数据,无法继续执行后续逻辑。 - 子进程的
read调用未处理返回值,无法判断数据是否读取完毕或遇到EOF。
修改后的代码
nicecmp.c(父进程)
核心修改:发送完数据后立即关闭管道写端,让子进程知道数据已全部发送。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main() { int pipe_to_loop[2]; // Pipe for sending data to loopcmp.c int pipe_from_loop[2]; // Pipe for receiving data from loopcmp.c // Create the pipes if (pipe(pipe_to_loop) == -1 || pipe(pipe_from_loop) == -1) { perror("Pipe creation failed"); return 1; } // Fork to create a child process for loopcmp.c pid_t pid = fork(); if (pid < 0) { perror("Fork failed"); return 1; } else if (pid == 0) { // Child process - loopcmp.c // Close unused pipe ends close(pipe_to_loop[1]); close(pipe_from_loop[0]); // Duplicate the read end of pipe_to_loop to stdin (file descriptor 0) dup2(pipe_to_loop[0], 0); // Duplicate the write end of pipe_from_loop to stdout (file descriptor 1) dup2(pipe_from_loop[1], 1); // Execute loopcmp.c execlp("./loopcmp", "./loopcmp", NULL); perror("Exec failed"); return 1; } else { // Parent process - nicecmp.c // Close unused pipe ends close(pipe_to_loop[0]); close(pipe_from_loop[1]); // Data to be sent to loopcmp.c const char *str1 = "Hello"; const char *str2 = "World"; int number = 42; // Send data to loopcmp.c through the pipe write(pipe_to_loop[1], str1, strlen(str1) + 1); write(pipe_to_loop[1], str2, strlen(str2) + 1); write(pipe_to_loop[1], &number, sizeof(int)); // 关键:关闭写端,告知子进程数据发送完毕 close(pipe_to_loop[1]); // Read data back from loopcmp.c int result; ssize_t read_bytes = read(pipe_from_loop[0], &result, sizeof(int)); if (read_bytes != sizeof(int)) { perror("Read result failed"); return 1; } // Print the result received from loopcmp.c printf("Received result from loopcmp.c: %d\n", result); // Close remaining pipe end close(pipe_from_loop[0]); } return 0; }
loopcmp.c(子进程)
核心修改:处理read返回值,按字节读取字符串直到遇到终止符或EOF,避免固定长度读取导致的阻塞。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main() { // Data buffers for receiving strings and integer char str1[100], str2[100]; int number; // 读取第一个字符串(直到'\0'或EOF) ssize_t bytes_read = 0; while (bytes_read < sizeof(str1) - 1) { ssize_t ret = read(0, str1 + bytes_read, 1); if (ret <= 0) break; // 遇到EOF或读取错误 if (str1[bytes_read] == '\0') break; // 字符串终止符 bytes_read++; } str1[sizeof(str1)-1] = '\0'; // 确保字符串安全终止 // 读取第二个字符串 bytes_read = 0; while (bytes_read < sizeof(str2) - 1) { ssize_t ret = read(0, str2 + bytes_read, 1); if (ret <= 0) break; if (str2[bytes_read] == '\0') break; bytes_read++; } str2[sizeof(str2)-1] = '\0'; // 读取整数 ssize_t int_read = read(0, &number, sizeof(int)); if (int_read != sizeof(int)) { fprintf(stderr, "Failed to read integer\n"); return 1; } // Print the received data(注:这些输出会写入管道,父进程未读取,若需要父进程接收需额外处理) printf("Received strings from nicecmp.c: %s, %s\n", str1, str2); printf("Received integer from nicecmp.c: %d\n", number); // Send the number 20 back to nicecmp.c through the pipe int result = 20; write(1, &result, sizeof(int)); return 0; }
额外说明
- 管道是字节流,没有边界,所以不能依赖固定长度读取,必须通过约定的分隔符(如字符串的
\0)或先发送数据长度来区分不同数据块。 - 始终处理
read/write的返回值,避免因读取错误或不完整导致的逻辑异常。
内容的提问来源于stack exchange,提问作者TheBeast3334
相关产品推荐
相关产品推荐

