设计思路
- 错误检测:在
write
和read
函数调用后立即检查返回值,判断是否发生错误。
- 错误记录:使用
errno
获取具体的错误代码,通过strerror
函数将错误代码转换为可读的错误信息字符串。
- 反馈机制:父进程可以通过标准输出或日志文件将错误信息反馈给用户;子进程可以将错误信息通过管道写回父进程,再由父进程处理并展示给用户。
- 程序稳定性:在发生错误后,根据错误的严重程度决定是继续尝试操作、调整程序行为还是安全退出。
关键代码片段
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define BUFFER_SIZE 1024
int main() {
int pipefd[2];
pid_t cpid;
char buffer[BUFFER_SIZE];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
ssize_t nbytes = read(pipefd[0], buffer, sizeof(buffer));
if (nbytes == -1) {
char errmsg[256];
snprintf(errmsg, sizeof(errmsg), "子进程读取错误: %s", strerror(errno));
// 将错误信息写回父进程
write(STDOUT_FILENO, errmsg, strlen(errmsg));
exit(EXIT_FAILURE);
}
buffer[nbytes] = '\0';
printf("子进程读取到: %s\n", buffer);
close(pipefd[0]);
exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd[0]); // 关闭读端
const char *msg = "Hello, 子进程!";
ssize_t nbytes = write(pipefd[1], msg, strlen(msg));
if (nbytes == -1) {
perror("父进程写入错误");
// 也可以在这里记录日志
exit(EXIT_FAILURE);
}
close(pipefd[1]);
// 等待子进程结束,处理子进程可能返回的错误信息
int status;
waitpid(cpid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
char child_errmsg[256];
ssize_t read_bytes = read(STDIN_FILENO, child_errmsg, sizeof(child_errmsg));
if (read_bytes > 0) {
child_errmsg[read_bytes - 1] = '\0'; // 移除换行符
printf("%s\n", child_errmsg);
}
}
exit(EXIT_SUCCESS);
}
}