Linux

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > Linux > Linux匿名管道和命名管道

Linux之匿名管道和命名管道详解

作者:爱吃芝麻汤圆

这篇文章主要介绍了Linux之匿名管道和命名管道的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

匿名管道

kubectl get pod -A | grep mysql

上面命令行里的「|」竖线就是一个管道,在命令行(如 Linux Shell 或 Windows CMD/PowerShell)中,管道操作符 | 的作用是将 前一个命令的标准输出(stdout) 传递给 后一个命令的标准输入(stdin)。但它默认 不会传递标准错误(stderr),这是它的核心行为特点。

1. 管道|的基本行为

command1 | command2

示例 1(stdout 被管道传递)

# ls 成功时,stdout(文件列表)会传递给 grep
ls /usr/bin | grep "python"

示例 2(stderr 未被管道传递)

# 如果目录不存在,错误信息会直接显示,不会传递给 grep
ls /nonexistent_dir | grep "error"

输出:

ls: cannot access '/nonexistent_dir': No such file or directory

(错误信息直接显示,grep 不会处理它)

2. 为什么|不处理 stderr

3. 原理

int pipe(int fd[2])

这里表示创建一个匿名管道,并返回了两个描述符,一个是管道的读取端描述符,另一个是管道的写入端描述符fd。注意,这个匿名管道是特殊的文件,只存在于内存,不存于文件系统中。

在这里插入图片描述

所谓的管道,就是内核里面的一串缓存。从管道的一段写入的数据,实际上是缓存在内核中的,另一端读取,也就是从内核中读取这段数据。另外,管道传输的数据是无格式的流且大小受限。

管道只能一端写入,另一端读出,所以上面这种模式容易造成混乱,因为父进程和子进程都可以同时写入,也都可以读出。那么,为了避免这种情况,通常的做法是:

在这里插入图片描述

在shell 里面执行 A | B 命令的时候,A 进程和 B 进程都是shell 创建出来的子进程,A 和 B 之间不存在父子关系,它俩的父进程都是 shell。

请添加图片描述

命名管道

简介

使用

int mkfifo(const char *pathname, mode_t mode);

创建 FIFO

使用 mkfifo 命令或 mkfifo() 函数创建:

mkfifo /tmp/myfifo  # 创建一个名为 /tmp/myfifo 的 FIFO

FIFO 的特点

半双工通信

# 终端1:写入数据
echo "Hello" > /tmp/myfifo

# 终端2:读取数据
cat /tmp/myfifo  # 输出 "Hello"

阻塞机制

数据是流式的

如何使用 FIFO?

(1)命令行测试

# 终端1:监听 FIFO(读)
cat /tmp/myfifo

# 终端2:发送数据(写)
echo "Hello FIFO" > /tmp/myfifo

终端1 会显示 Hello FIFO

(2)C 语言示例

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main() {
    mkfifo("/tmp/myfifo", 0644);  // 创建 FIFO

    int fd = open("/tmp/myfifo", O_WRONLY);  // 以写方式打开
    write(fd, "Hello", 6);  // 写入数据
    close(fd);

    return 0;
}

常见问题

Q1: FIFO 和普通文件有什么区别?

Q2: FIFO 和匿名管道(|)有什么区别?

Q3: 如果 FIFO 已经存在,再创建会怎样?

原理

1. 普通文件 vs. 命名管道(FIFO)

普通文件(如 a.txt):

命名管道(FIFO)

2. 命名管道的工作原理

(1)创建 FIFO

当执行 mkfifo /tmp/myfifo 时:

  1. 磁盘上创建一个 空文件(只有 inode,没有数据块)。
  2. 操作系统内核维护一个 内存缓冲区(用于存储进程间传递的数据)。

(2)进程 A 写入数据

echo "Hello" > /tmp/myfifo

(3)进程 B 读取数据

cat /tmp/myfifo

3. 关键点解析

(1)文件描述符与内核结构

每个进程打开 FIFO 时,内核会 复用同一个 struct file(通过引用计数 ref 管理)。

(2)为什么数据不刷盘?

(3)半双工通信

4. 类比理解

把 FIFO 想象成 一条水管

写入端:进程 A 往水管里倒水(数据)。

读取端:进程 B 从水管接水(数据)。

特性

总结

特性命名管道(FIFO)普通文件
存储位置内存缓冲区磁盘
刷盘永不刷盘定期刷盘
多进程访问共享同一缓冲区可能数据不同步
阻塞行为读/写会阻塞无阻塞
用途进程间通信数据存储

简单来说:

FIFO 是 披着文件外衣的内存管道,让进程可以通过文件路径名通信,数据 不落盘,速度极快!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文