MST

星途 面试题库

面试题:C语言匿名管道通信中的父子进程数据交互

在Linux环境下使用C语言进行匿名管道通信时,描述一下父子进程如何通过匿名管道实现数据的单向传输?请写出关键代码片段,并解释每一步的作用。
45.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
  1. 关键代码片段
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define BUFFER_SIZE 1024

int main() {
    int pipefd[2];
    pid_t cpid;
    char buf[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[0]); // 关闭读端,因为子进程只写
        const char *msg = "Hello, parent from child!";
        if (write(pipefd[1], msg, strlen(msg)) != strlen(msg)) {
            perror("write");
            exit(EXIT_FAILURE);
        }
        close(pipefd[1]); // 写完关闭写端
        exit(EXIT_SUCCESS);
    } else {            // 父进程
        close(pipefd[1]); // 关闭写端,因为父进程只读
        ssize_t nbytes = read(pipefd[0], buf, BUFFER_SIZE);
        if (nbytes == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        printf("Received from child: %.*s\n", (int)nbytes, buf);
        close(pipefd[0]); // 读完关闭读端
        wait(NULL);       // 等待子进程结束
    }

    return 0;
}
  1. 步骤解释
    • 创建匿名管道
      if (pipe(pipefd) == -1) {
          perror("pipe");
          exit(EXIT_FAILURE);
      }
      
      • pipe函数创建一个匿名管道,它返回两个文件描述符,pipefd[0]用于读管道,pipefd[1]用于写管道。如果pipe函数调用失败,打印错误信息并退出程序。
    • 创建子进程
      cpid = fork();
      if (cpid == -1) {
          perror("fork");
          exit(EXIT_FAILURE);
      }
      
      • fork函数创建一个新的子进程。父进程和子进程都会从fork函数之后继续执行。如果fork函数调用失败,打印错误信息并退出程序。
    • 子进程处理
      if (cpid == 0) {
          close(pipefd[0]);
          const char *msg = "Hello, parent from child!";
          if (write(pipefd[1], msg, strlen(msg)) != strlen(msg)) {
              perror("write");
              exit(EXIT_FAILURE);
          }
          close(pipefd[1]);
          exit(EXIT_SUCCESS);
      }
      
      • 子进程关闭读端pipefd[0],因为它只需要向管道写数据。
      • 子进程通过write函数向管道的写端pipefd[1]写入数据。如果写入失败,打印错误信息并退出程序。
      • 写完数据后,关闭写端pipefd[1],然后子进程正常退出。
    • 父进程处理
      else {
          close(pipefd[1]);
          ssize_t nbytes = read(pipefd[0], buf, BUFFER_SIZE);
          if (nbytes == -1) {
              perror("read");
              exit(EXIT_FAILURE);
          }
          printf("Received from child: %.*s\n", (int)nbytes, buf);
          close(pipefd[0]);
          wait(NULL);
      }
      
      • 父进程关闭写端pipefd[1],因为它只需要从管道读数据。
      • 父进程通过read函数从管道的读端pipefd[0]读取数据到缓冲区buf。如果读取失败,打印错误信息并退出程序。
      • 打印接收到的数据,然后关闭读端pipefd[0]
      • 父进程调用wait函数等待子进程结束,防止产生僵尸进程。