MST

星途 面试题库

面试题:C语言Linux匿名管道错误处理优化

假设在一个多进程程序中使用C语言创建了匿名管道,父进程向管道写入数据,子进程从管道读取数据。如果管道写入或读取时发生错误,怎样设计一个高效的错误处理机制,既能确保程序稳定性,又能及时反馈错误信息给用户?请描述设计思路并给出关键代码片段。
24.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 错误检测:在writeread函数调用后立即检查返回值,判断是否发生错误。
  2. 错误记录:使用errno获取具体的错误代码,通过strerror函数将错误代码转换为可读的错误信息字符串。
  3. 反馈机制:父进程可以通过标准输出或日志文件将错误信息反馈给用户;子进程可以将错误信息通过管道写回父进程,再由父进程处理并展示给用户。
  4. 程序稳定性:在发生错误后,根据错误的严重程度决定是继续尝试操作、调整程序行为还是安全退出。

关键代码片段

#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);
    }
}