【Linux】Linux进程通信核心技能:搞懂命名管道,轻松了解无血缘进程通信难题!
前言:欢迎各位光临本博客,这里小编带你直接手撕,文章并不复杂,愿诸君**耐其心性,忘却杂尘,道有所长!!!!
IF’Maxue:个人主页
🔥 个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》
⛺️生活是默默的坚持,毅力是永久的享受。不破不立!
文章目录
我推荐各位大佬在看这篇这张之前先对匿名管道有一个大致的了解,因为这节内容是基于匿名管道来的,是基这里我给大佬们两个链接,帮助佬们更好的找到匿名管道的知识点!!!
MAXUE的匿名管道:https://blog.ZEEKLOG.net/wheeldown/article/details/152418393?spm=1001.2014.3001.5501
bangbang佬的匿名管道:https://blog.ZEEKLOG.net/bang___bang_/article/details/132128822
命名管道
1. 为什么需要命名管道?
我们知道,匿名管道有个关键局限——只能用于有血缘关系的进程(比如父进程和子进程)。那如果两个完全不相关的进程(比如两个独立启动的程序)需要通信,该怎么办?这就需要命名管道来解决。
2. 核心原理:从“文件共享”看懂命名管道
要理解命名管道,先搞懂一个底层问题:两个进程打开同一个文件,文件会在内存中加载两次吗?

答案是不会,因为操作系统设计时就遵循“不做无用功”的原则,具体逻辑如下:
- 进程A打开文件后,会生成一个专属的
struct file结构体,里面包含文件的inode(索引节点)和文件缓冲区。 - 当进程B要打开同一个文件时,会生成自己的
struct file(因为两个进程的读写位置可能不同),但它的inode和文件缓冲区会直接指向进程A的对应地址,不会重复加载。
下面的流程图清晰展示了这个过程:

从这个过程能发现命名管道的本质:
- 两个进程通过“打开同一路径下的同一个文件”,共享同一份资源。
- 因为这个“路径”有唯一的名字,所以这种管道被称为“命名管道”。
- 如果你已经懂了匿名管道的原理,理解命名管道会更轻松。
另外,命名管道对应的“管道文件”有个特性:仅用于进程间通信,只会被打开使用,无需像普通文件那样刷新数据。

3. Linux命令:创建命名管道
在Linux命令行中,用mkfifo命令就能创建命名管道,步骤如下:
- 命令格式:
mkfifo + 命名管道的名字。 - 示例:输入
mkfifo fifo,就能创建一个名为fifo的命名管道。
创建后,用ll命令查看目录,会发现多了一个fifo文件,它的权限前缀是p——这个p就代表“管道文件”,说明创建成功了。

4. 命名管道代码示例
下面的代码仅为演示核心逻辑,方便理解,不代表完整的工业级代码。要在代码中创建命名管道,首先得了解mkfifo接口——可以通过man mkfifo命令查看接口详情。

4.1 代码创建命名管道(写方式打开)
以下代码演示如何创建命名管道,并以“写”的方式打开,向管道中写入数据:

#include<iostream>#include<fcntl.h>#include<unistd.h>#include<sys/stat.h>#include<sys/types.h>#defineFIFO_FILE"fifo"intmain(){// 创建命名管道int ret =mkfifo(FIFO_FILE,0666);if(ret ==-1){perror("mkfifo");return1;} std::cout <<"fifo created success"<< std::endl;// 以写方式打开管道int fd =open(FIFO_FILE, O_WRONLY);if(fd ==-1){perror("open");return1;} std::cout <<"open fifo success, write..."<< std::endl;// 向管道写入数据constchar* msg ="hello named pipe";write(fd, msg,sizeof(msg));// 关闭文件描述符close(fd);return0;}运行后的结果如下,能看到数据成功写入管道:
注意打开的时候要client和sever都打开

4.2 代码读取命名管道数据
以下代码演示如何以“读”的方式打开命名管道,读取管道中的数据:
{ std::cerr <<"open fifo error"<< std::endl;return2;}char buffer[1024];while(true){int n =read(fd, buffer,sizeof(buffer)-1);if(n >0){ buffer[n]=0; std::cout <<"client say# "<< buffer << std::endl;}}close(fd);return0;}到这里这只是一个演示,以上是命名管道的理论基础,完整的模拟代码会在下一期出!!!!