在Linux系统中,管道是一种常见的进程间通信(IPC)机制,它可以把一个进程的输出作为另一个进程的输入。管道主要有两种类型:无名管道和命名管道。
无名管道是单向的,只能在有亲缘关系的进程间使用。它通过调用pipe()
函数创建,该函数会填充一个整型数组包含两个元素,其中fd[0]
用于读取,而fd[1]
用于写入。
以下是一个使用无名管道的示例代码:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int fd[2];
pid_t pid;
char buf;
if (pipe(fd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if ((pid = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
/* 子进程 */
close(fd[1]); // 关闭写端
while (read(fd[0], &buf, 1) > 0) {
write(STDOUT_FILENO, &buf, 1);
}
close(fd[0]);
_exit(EXIT_SUCCESS);
} else {
/* 父进程 */
close(fd[0]); // 关闭读端
write(fd[1], "Hello, World!", 14);
close(fd[1]);
wait(NULL);
}
return 0;
}
在这个例子中,父进程创建了一个管道,然后创建了一个子进程。父进程关闭了读端,通过写端发送数据“Hello, World!”,子进程关闭了写端,通过读端读取数据并打印。
命名管道(FIFO)允许无亲缘关系进程间通信。它通过mkfifo()
函数创建一个文件,然后像读写文件一样对它进行操作。
以下是一个使用命名管道的示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFO_NAME "/tmp/my_fifo"
int main() {
char buf_r;
int fd;
// 创建命名管道
if (mkfifo(FIFO_NAME, 0666) < 0) {
perror("mkfifo");
exit(1);
}
// 打开管道进行读取
fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK, 0);
if (fd < 0) {
perror("open");
exit(1);
}
while (1) {
int n = read(fd, &buf_r, 1);
if (n > 0) {
printf("Received: %c\n", buf_r);
}
}
close(fd);
unlink(FIFO_NAME);
return 0;
}
在这个例子中,首先创建了一个命名管道,然后打开它进行非阻塞读取。这样,即使当前没有数据可读,读取操作也不会阻塞,可以继续执行其他任务。