在Linux中,管道(pipe)是一种用于在不同进程之间传输数据的机制。管道通信通常分为两种类型:匿名管道(unnamed pipe)和命名管道(named pipe,也称为FIFO)。下面分别介绍这两种管道的实现方法。
匿名管道是一种半双工的通信方式,只能在具有亲缘关系的进程之间使用(例如父子进程)。匿名管道通过pipe()系统调用创建。
#include <unistd.h>
int pipe(int pipefd[2]);
pipe()函数接受一个包含两个整数的数组pipefd,pipefd[0]用于读取数据,pipefd[1]用于写入数据。
以下是一个简单的示例,展示了如何使用匿名管道在父子进程之间传输数据:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
int pipefd[2];
pid_t pid;
char buffer[1024];
// 创建匿名管道
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
// 从管道读取数据
ssize_t bytes_read = read(pipefd[0], buffer, sizeof(buffer));
if (bytes_read > 0) {
printf("Child received: %s\n", buffer);
}
close(pipefd[0]); // 关闭读端
exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd[0]); // 关闭读端
// 向管道写入数据
const char *message = "Hello from parent!";
ssize_t bytes_written = write(pipefd[1], message, strlen(message) + 1);
if (bytes_written > 0) {
printf("Parent sent: %s\n", message);
}
close(pipefd[1]); // 关闭写端
wait(NULL); // 等待子进程结束
}
return 0;
}
命名管道是一种全双工的通信方式,可以在任意进程之间使用。命名管道通过mkfifo()系统调用创建。
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
mkfifo()函数接受两个参数:pathname是命名管道的路径名,mode是命名管道的权限模式。
以下是一个简单的示例,展示了如何使用命名管道在两个进程之间传输数据:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
int main() {
const char *fifo_path = "/tmp/myfifo";
int fd;
char buffer[1024];
// 创建命名管道
if (mkfifo(fifo_path, 0666) == -1) {
perror("mkfifo");
exit(EXIT_FAILURE);
}
// 打开命名管道
fd = open(fifo_path, O_RDWR);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 向命名管道写入数据
const char *message = "Hello from process!";
ssize_t bytes_written = write(fd, message, strlen(message) + 1);
if (bytes_written > 0) {
printf("Process sent: %s\n", message);
}
// 从命名管道读取数据
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read > 0) {
printf("Process received: %s\n", buffer);
}
close(fd); // 关闭命名管道
unlink(fifo_path); // 删除命名管道
return 0;
}
通过以上示例,你可以了解如何在Linux中使用匿名管道和命名管道实现进程间通信。