- 关键代码片段
#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;
}
- 步骤解释
- 创建匿名管道:
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
函数等待子进程结束,防止产生僵尸进程。