Linux 进程通信 -- 管道

1、管道简介

管道是Linux提供的进程间通信机制之一,允许通信进程之间通过文件读写的方式单向传递数据。内核实现的文件系统pipefs,会在内核为每个管道文件分配一个的环形缓存区,以支持读/写操作。进程可以使用两种类型的管道进行通信:

  • 匿名管道:只支持在父子进程、兄弟进程之间通信。一般使用方式为,父进程调用pipe()创建匿名管道,fork()的子进程默认继承父进程打开的管道
  • 命名管道:支持任意的进程通过管道通信。进程通信前,需要先创建fifo类型特殊的文件,然后读写进程分别打开该文件进行读写

2、 管道机制

2.1 匿名使用示例

举一个常见的场景,我们在shell(如bash)执行下面的命令行,该命令行的意思是,将cat 命令执行的标准输出流,重定向至grep命令的输入流。其中'|'字符就是让bash知道,这里有左右两边的命令,需要通过管道进行数据传输。

~ $ cat '/etc/passwd' | grep 'docker'

忽略bash对命令行的解析过程,可以用下面一段简单的代码,展示bash是怎么实现命令之间的管道传输的。

#include 
#include 
#include 
#include 
#include 
#include 
    
int main(int argc, char** argv) {
    int fd[2];
    // fd[0]为管道写端, fd[1]为管道文件读端
    if (pipe(fd) != 0) {
        exit(errno);
    }
        
    int pid = fork();
    if (pid == -1) {
        exit(errno);
    } else if (pid == 0) {
        // 关闭标准输出
        close(1);
        // 利用dup(fd[1]])从管道写端复制一个描述符,新文件新的文件为最小可用的文件描述符,即上面关闭的1,所以这里是将标准输出重定向至管道写端
        dup(fd[1]);
        
        // 关闭管道读端
        close(fd[0]);
        // 关闭已复制的文件描述符
        close(fd[1]);
        
        // 重定向完成,加载命令
        execlp("cat", "/etc/passwd", NULL);
    } else {
        close(0);
        dup(fd[0]);
        close(fd[1]);
        close(fd[0]);
  

你可能感兴趣的:(linux,shell,linux)