news 2026/3/1 5:41:38

进程间通信--命名管道

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
进程间通信--命名管道

第一部分:命名管道 (FIFO) —— 给管道起个名

1. 核心概念
  • 匿名管道:在内存里,没有名字。只有父子进程能通过文件描述符看到它。
  • 命名管道在磁盘上有文件名
    • 因为它有路径(比如/tmp/mypipe),所以任何进程,只要知道这个路径,有权限,就可以通过打开文件的方式来打开它。
    • 关键点:虽然它在磁盘上有个文件壳子,但数据本身是不存硬盘的。数据依然是在内核的内存缓冲区里流动。一旦断电或重启,数据就没了,但那个文件壳子还在。
2. 直观体验

你可以不写代码,直接在 Linux 终端感受一下。

  1. 创建管道:使用命令mkfifo

Bash

mkfifo mypipe
  1. 查看属性

Bash

ls -l mypipe # 输出: prw-r--r-- 1 user group 0 ... mypipe

注意开头的p,这代表它是一个Pipe文件。

  1. 测试通信
    • 开一个终端 A(读端):cat mypipe
      • 现象:卡住了(阻塞)。因为它在等有人来写。
    • 开终端 B(写端):echo "Hello FIFO" > mypipe
      • 现象:终端 A 立刻打印出 "Hello FIFO",然后命令结束。

第二部分:代码实战 —— Server & Client 通信模型

为了演示“毫无关系”的进程通信,我们需要写两个独立的程序

  1. server.cpp:负责创建管道,读取数据(读端)。
  2. client.cpp:负责打开管道,发送数据(写端)。

这其实就是最简陋的服务器-客户端模型。

1. Server 端 (server.cpp)
#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <errno.h> #define FIFO_FILE "./mypipe" int main() { // 1. 创建命名管道 // 参数2:权限掩码 (类似 mkdir) if (mkfifo(FIFO_FILE, 0666) < 0) { if (errno != EEXIST) { // 如果文件已存在,不算错 perror("mkfifo"); return 1; } } std::cout << "Server: FIFO created, waiting for client..." << std::endl; // 2. 打开管道 (读方式) // 注意:这里会【阻塞】,直到有别的进程以写方式打开同一个 FIFO int fd = open(FIFO_FILE, O_RDONLY); if (fd < 0) { perror("open"); return 2; } std::cout << "Server: Client connected!" << std::endl; // 3. 循环读取 char buffer[1024]; while (true) { memset(buffer, 0, sizeof(buffer)); ssize_t s = read(fd, buffer, sizeof(buffer) - 1); if (s > 0) { // 读到数据 std::cout << "Client Say# " << buffer << std::endl; } else if (s == 0) { // 写端关闭了 (Client 退出) std::cout << "Client quit, Server quit." << std::endl; break; } else { perror("read"); break; } } close(fd); return 0; }
2. Client 端 (client.cpp)
#include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #define FIFO_FILE "./mypipe" int main() { std::cout << "Client: Trying to connect server..." << std::endl; // 1. 打开管道 (写方式) // 只要 Server 端创建了 FIFO,Client 直接打开即可 int fd = open(FIFO_FILE, O_WRONLY); if (fd < 0) { perror("open"); return 1; } std::cout << "Client: Connected! Please enter message:" << std::endl; // 2. 循环写入 std::string line; while (true) { std::cout << "> "; if (!std::getline(std::cin, line)) break; // Ctrl+D 退出 write(fd, line.c_str(), line.size()); } close(fd); return 0; }
3. 运行步骤
  1. 编译:g++ server.cpp -o serverg++ client.cpp -o client
  2. 先在一个终端运行./server。你会发现它打印完 "waiting for client..." 就卡住了。
  3. 在另一个终端运行./client
  4. 奇迹发生:Server 端瞬间提示 "Client connected!"。
  5. 你在 Client 输入什么,Server 就能收到什么。

第三部分:深入原理 ——open的秘密

你可能注意到了,Server 在open的时候卡住了。这是命名管道的一个重要特性。

同步规则

  • 读端打开 (O_RDONLY):会阻塞,直到有另一个进程以写方式打开同一个 FIFO。
  • 写端打开 (O_WRONLY):会阻塞,直到有另一个进程以读方式打开同一个 FIFO。

为什么这样设计?

这就好比打电话。

  • Server 拿起了听筒(读端打开),如果对面没人拨号(写端未打开),Server 拿着听筒听空气没有任何意义,所以系统让它先等着。
  • Client 拨了号(写端打开),如果对面没人接(读端未打开),话说给谁听呢?所以也得等着。
  • 只有两头都通了,open才会同时返回,连接建立成功。

第四部分:匿名管道 vs 命名管道

这两种管道是 Linux IPC 的基础,我们做一个对比总结:

特性

匿名管道 (Pipe)

命名管道 (FIFO)

可见性

内存中,无文件名

磁盘上有文件名

通信范围

仅限血缘关系进程 (父子/兄弟)

任意进程 (只要权限允许)

创建方式

pipe()

mkfifo()

生命周期

随进程结束而销毁

随文件系统 (即使进程全退出了,文件还在)

本质

都是内核中的一块缓冲区

同左

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/27 9:09:43

AppleRa1n:iOS激活锁绕过的终极解决方案指南

AppleRa1n&#xff1a;iOS激活锁绕过的终极解决方案指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 面对iPhone因Apple ID密码遗忘或二手设备账户问题而无法激活的困境&#xff0c;AppleRa1n提供了…

作者头像 李华
网站建设 2026/2/27 1:36:05

RTL8852BE驱动:Linux无线网络兼容性问题的完整解决方案指南

RTL8852BE驱动&#xff1a;Linux无线网络兼容性问题的完整解决方案指南 【免费下载链接】rtl8852be Realtek Linux WLAN Driver for RTL8852BE 项目地址: https://gitcode.com/gh_mirrors/rt/rtl8852be RTL8852BE驱动是一个专门为Linux系统设计的开源驱动程序&#xff0…

作者头像 李华
网站建设 2026/2/28 18:16:32

Obsidian样式定制完全指南:从入门到精通的主题个性化技巧

Obsidian样式定制完全指南&#xff1a;从入门到精通的主题个性化技巧 【免费下载链接】obsidian-style-settings A dynamic user interface for adjusting theme, plugin, and snippet CSS variables within Obsidian 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-…

作者头像 李华