在Linux中,管道(pipe)是一种用于在不同进程之间传输数据的通信机制。管道可以分为匿名管道(unnamed pipe)和命名管道(named pipe,也称为FIFO)。这里我们将介绍如何使用匿名管道进行数据交换。
匿名管道是一种半双工的通信方式,只能在具有亲缘关系的进程之间使用(例如父子进程)。它使用内核缓冲区来存储数据,因此需要注意缓冲区的大小限制。
以下是使用匿名管道进行数据交换的基本步骤:
pipe()
系统调用创建一个管道。它会返回两个文件描述符,一个用于读取(fd[0]),另一个用于写入(fd[1])。#include <unistd.h>
int pipe(int fd[2]);
fork()
系统调用创建一个子进程。fork()
会返回两次,一次在父进程中,一次在子进程中。在子进程中,fork()
返回0;在父进程中,fork()
返回子进程的进程ID。#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
#include <unistd.h>
void close(int fd);
read()
和write()
系统调用在管道中传输数据。#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
以下是一个简单的示例,展示了如何使用匿名管道在父子进程之间传输数据:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
int fd[2];
pid_t pid;
char buffer[128];
// 创建管道
if (pipe(fd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(fd[1]); // 关闭写入端
// 从管道读取数据
ssize_t bytes_read = read(fd[0], buffer, sizeof(buffer));
if (bytes_read > 0) {
buffer[bytes_read] = '\0';
printf("子进程收到数据: %s\n", buffer);
}
close(fd[0]);
} else { // 父进程
close(fd[0]); // 关闭读取端
// 向管道写入数据
const char *message = "Hello from parent!";
ssize_t bytes_written = write(fd[1], message, strlen(message) + 1);
if (bytes_written > 0) {
printf("父进程发送数据: %s\n", message);
}
close(fd[1]);
}
return 0;
}
编译并运行此程序,您将看到父进程发送数据到子进程,子进程从管道接收并打印数据。
请注意,这个示例仅用于演示目的。在实际应用中,您可能需要处理错误情况、使用循环进行多次数据交换等。此外,如果需要在无亲缘关系的进程之间进行通信,可以考虑使用命名管道(FIFO)。