Linux命名管道(FIFO)通信:从原理到实操,一文搞懂跨进程通信

Linux命名管道(FIFO)通信:从原理到实操,一文搞懂跨进程通信

🔥个人主页:Cx330🌸

❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》

《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔

《Git深度解析》:版本管理实战全解

🌟心向往之行必能至


🎥Cx330🌸的简介:


目录

前言:

一、先搞懂:命名管道(FIFO)是什么?

1. 命名管道的本质

2. 命名管道的核心特点

3. 命名管道与匿名管道的对比

二. 命名管道的创建方式

2.1 命令行创建(mkfifo 命令)

2.2 代码创建(mkfifo 函数)

2.3 命名管道的打开规则

三、实操实现:手搓命名管道通信

3.1 前置准备(Makefile && comm.h)

3.2 服务端程序(server.c)

3.3 客户端程序(client.c)

3.4 编译运行

四、命名管道的实际应用场景

五、常见坑点总结(必看)

六、总结


前言:

在Linux进程间通信(IPC)中,管道是最基础、最常用的通信方式之一,但我们平时接触的“匿名管道”有一个致命缺陷——只能用于有血缘关系的进程(父进程与子进程、兄弟进程),无法实现无关联进程间的通信。

命名管道(简称FIFO),正是为解决这个问题而生。它给管道赋予了一个“文件名”,通过文件系统作为媒介,让任意两个进程(无论是否有血缘关系)都能通过这个“命名”实现数据交互。今天这篇博客,就从原理到实操,手把手教你搞懂Linux命名管道,亲手实现跨进程通信。

一、先搞懂:命名管道(FIFO)是什么?

1. 命名管道的本质

命名管道和匿名管道的核心通信逻辑完全一致——都是基于“字节流”的半双工通信(同一时刻只能单向传输数据),底层都是内核中的缓冲区。

两者的核心区别的是:命名管道有一个可见的文件系统入口(一个以.fifo或.pipe为后缀的文件),这个文件只是一个“标识”,不存储实际数据(数据仍在内存缓冲区中);而匿名管道没有文件入口,只能通过父子进程继承文件描述符来通信

简单来说:匿名管道是“隐式的、血缘专属”,命名管道是“显式的、通用的”,只要知道FIFO文件的路径,任意进程都能与之通信。

2. 命名管道的核心特点

  • 跨进程通信:无血缘关系的进程(如两个独立的程序),只要知道FIFO文件路径,就能通过它通信;
  • 半双工通信:数据只能单向流动,若要实现双向通信,需要创建两个FIFO(一个用于A→B,一个用于B→A);
  • 基于文件标识:FIFO文件存在于文件系统中,进程通过打开这个文件,获取读写文件描述符,进而实现通信;
  • 阻塞特性:默认情况下,打开FIFO的读端会阻塞,直到有进程打开写端;打开写端也会阻塞,直到有进程打开读端(可通过O_NONBLOCK设置为非阻塞);
  • 生命周期:FIFO文件不会随进程退出而自动删除,需要手动删除(rm命令或unlink函数),否则会一直存在于文件系统中。

3. 命名管道与匿名管道的对比

为了更清晰区分,做一个简单对比表,避免混淆:

对比维度

匿名管道(pipe)

命名管道(FIFO)

通信范围

有血缘关系的进程(父子、兄弟)

任意进程(无血缘关系也可)

标识方式

无文件标识,通过文件描述符继承

有文件系统入口(FIFO文件)

创建方式

通过pipe()系统调用创建

通过mkfifo()系统调用或mkfifo命令创建

生命周期

随进程退出而销毁(文件描述符关闭)

随FIFO文件删除而销毁,进程退出不影响文件

使用场景

父子进程间简单通信(如shell管道)

无关联进程间通信(如两个独立程序交互)


二. 命名管道的创建方式

命名管道有两种创建方式:命令行创建和代码创建,本质都是在文件系统中生成一个 FIFO 类型的文件。

2.1 命令行创建(mkfifo 命令)

直接通过mkfifo命令创建命名管道,语法简单,适合快速测试:

# 创建名为myfifo的命名管道 mkfifo myfifo # 查看管道文件(类型标识为p) ls -l myfifo 
我们可以发现,这里创建的管道文件(最前面的标识是p开头),就算我们是不停的在往里面进行写操作,但是它的文件大小是一直不变的,验证了我们上面图中所说的它不是一个普通文件。

2.2 代码创建(mkfifo 函数)

通过 mkfifo()系统调用在代码中创建命名管道,需指定管道路径和权限,原型如下:

#include <sys/stat.h> #include <sys/types.h> // 参数:pathname-管道路径;mode-权限(如0644) int mkfifo(const char *pathname, mode_t mode); 

代码示例(创建命名管道)

#include <stdio.h> #include <sys/stat.h> #include <sys/types.h> #include <errno.h> #define FIFO_PATH "./myfifo" int main() { // 创建命名管道,权限0644(所有者读+写,其他读) int ret = mkfifo(FIFO_PATH, 0644); if (ret == -1) { // 若管道已存在,errno为EEXIST,可忽略该错误 if (errno != EEXIST) { perror("mkfifo error"); return 1; } printf("命名管道已存在\n"); } else { printf("命名管道创建成功\n"); } return 0; } 

2.3 命名管道的打开规则

命名管道的打开(open())行为与普通文件不同,核心是 “读端与写端的同步”—— 仅当管道的读端和写端都被打开后,通信才能正常进行,具体规则如下:

  • O_RDONLY:以只读方式打开(读端),默认阻塞,直到有进程以O_WRONLY方式打开;
  • O_WRONLY:以只写方式打开(写端),默认阻塞,直到有进程以O_RDONLY方式打开;
  • O_RDWR:以读写方式打开,不阻塞,直接打开(同时具备读和写权限,可实现单向通信的 “自我循环”)
注意:实际开发中,建议读端O_RDONLY打开,写端O_WRONLY打开,避免使用O_RDWR(可能导致通信逻辑混乱)。

三、实操实现:手搓命名管道通信

  • server.c:作为服务端,监听管道,接收客户端消息并打印;
  • client.c:作为客户端,向管道发送消息,实现双向交互。

3.1 前置准备(Makefile && comm.h)

Makefile:

all:client server client:client.cc g++ -o $@ $^ -std=c++11 server:server.cc g++ -o $@ $^ -std=c++11 .PHONY:clean clean: rm -f client server

comm.h:

#pragma once #include <string> const std::string fifoname="fifo";

3.2 服务端程序(server.c)

#include <iostream> #include <cstdio> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include "comm.h" int main() { // 1.创建管道文件 umask(0); int n=mkfifo(fifoname.c_str(),0666); if(n<0) { perror("mkfifo"); return 1; } // 2.打开管道文件 int rfd=open(fifoname.c_str(),O_RDONLY); if(rfd<0) { perror("open"); return 2; } char inbuffer[1024]; // 3.进行通信 while(true) { ssize_t n=read(rfd,inbuffer,sizeof(inbuffer)-1); if(n>0) { inbuffer[n]=0; std::cout<<"client say# "<<inbuffer<<std::endl; } else if(n==0) { // 写端关闭了 break; } else { perror("read"); break; } } // 4.关闭 close(rfd); // 5.删除管道文件 unlink(fifoname.c_str()); return 0; }

3.3 客户端程序(client.c)

#include <iostream> #include <string> #include <cstdio> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "comm.h" int main() { int wfd=open(fifoname.c_str(),O_WRONLY); if(wfd<0) { perror("open"); return 1; } std::string outstring; while(true) { std::cout<<"Please Enter@ "; std::cin>>outstring; write(wfd,outstring.c_str(),outstring.size());// 要不要写'\0'? 不需要! } close(wfd); return 0; }

3.4 编译运行


四、命名管道的实际应用场景

命名管道因其“跨进程、简单易用”的特点,在Linux开发中应用广泛,常见场景包括:

  • 后台服务与前台程序通信:如后台守护进程(如日志服务),通过FIFO接收前台程序发送的日志指令,实现日志的动态控制;
  • 多个独立程序的数据交互:如两个不同的服务程序(如数据库服务和缓存服务),通过FIFO传递数据,无需复杂的IPC机制;
  • shell脚本间通信:在shell脚本中,通过mkfifo命令创建FIFO,实现两个脚本之间的数据传输(比匿名管道更灵活);
  • 简单的客户端/服务器模型:基于FIFO实现简单的C/S架构,客户端向FIFO写入请求,服务器从FIFO读取请求并处理,返回结果。

五、常见坑点总结(必看)

  • 忘记处理阻塞:打开FIFO时未设置O_NONBLOCK,导致进程一直阻塞,误以为程序卡死;
  • 忽略SIGPIPE信号:读端关闭后,写端继续写入,导致进程崩溃;
  • FIFO文件残留:未用unlink()删除FIFO,下次创建时报错;
  • 路径不一致:读端和写端使用的FIFO路径不同,导致无法通信;
  • 权限问题:mkfifo()设置的权限过低(如0600),导致其他进程无法打开FIFO,建议设置为0666;
  • 数据错乱:未处理字节流无边界问题,读端读取的数据不完整或拼接错误。

六、总结

命名管道(FIFO)是Linux跨进程通信的基础方式,核心是“通过文件系统标识,实现任意进程间的字节流通信”。它继承了匿名管道的简单性,又解决了匿名管道“只能用于血缘进程”的缺陷,是入门IPC开发的必学知识点。

本文通过“原理→API→实操→避坑”的流程,手把手教你实现命名管道的单方向和双向通信,代码可直接复用。重点掌握FIFO的阻塞特性、SIGPIPE信号处理和文件删除问题,就能避免绝大多数踩坑场景。

实际开发中,若需要更高效、更复杂的通信(如消息优先级、双向通信的更优实现),可后续学习消息队列、共享内存等IPC机制,但命名管道的核心思想(字节流、文件标识),是理解所有IPC机制的基础。

最后,附上本文所有实操代码的仓库链接,方便大家下载测试和修改:fifo

Read more

前端静态项目快速启动:python -m http.server 4173 与 npx serve . 全解析

前端静态项目快速启动:python -m http.server 4173 与 npx serve . 全解析 在前端开发或文件共享场景中,我们经常会用到 python -m http.server 4173 和 npx serve . 这两个简单命令,它们能快速启动服务器预览前端项目,但很多人会疑惑:前端代码如此复杂,为何这两个简单命令就能实现“启动”?本文将从命令解析、工作原理、核心区别等方面全面拆解,帮你彻底弄懂背后的逻辑。 一、命令一:python -m http.server 4173 详细解释 1. 核心作用 在当前命令行所在的目录下,快速启动一个简单的HTTP文件服务器(静态文件服务器),该服务器会监听本机的4173端口,允许通过浏览器或其他HTTP客户端访问该目录下的文件及子目录。它常用来快速共享文件、本地调试简单静态网页(HTML/CSS/JS)

By Ne0inhk

Qwen3-0.6B-FP8基础教程:6亿参数+FP8量化+多语言支持详解

Qwen3-0.6B-FP8基础教程:6亿参数+FP8量化+多语言支持详解 想快速体验一个既小巧又聪明的AI助手吗?今天要介绍的Qwen3-0.6B-FP8,就是一个让你在普通电脑上也能轻松玩转大模型的“神器”。它只有6亿参数,经过FP8量化后,显存占用不到2GB,却能流畅地进行多轮对话、代码生成甚至复杂推理。 这篇文章,我就带你从零开始,手把手教你如何部署和使用这个模型,让你在10分钟内就能和它愉快地聊天。 1. 为什么选择Qwen3-0.6B-FP8? 在开始动手之前,我们先花一分钟了解一下,这个模型到底有什么特别之处,值不值得你花时间去折腾。 简单来说,Qwen3-0.6B-FP8是阿里通义千问家族的最新成员,主打一个“小而美”。它最大的亮点,就是用上了FP8量化技术。你可以把量化想象成给模型“瘦身”,在不怎么影响它“智商”(性能)的前提下,让它占用的空间(显存)大大减少。 对于咱们普通开发者或者爱好者来说,这意味着什么呢? * 门槛极低:你不再需要昂贵的专业显卡。一张显存大于2GB的消费级显卡(比如RTX 3060)甚至一些集成显卡就能跑起来。

By Ne0inhk

中兴B863AV3.1-M2卡刷固件实战:从萌虎动画到无线网卡全解析

1. 中兴B863AV3.1-M2卡刷固件入门指南 第一次接触中兴B863AV3.1-M2刷机的朋友可能会觉得有些复杂,但其实只要跟着步骤来,整个过程并不难。这个固件最大的亮点就是加入了萌虎动画和无线网卡支持,让原本功能受限的机顶盒焕发新生。 我去年第一次刷这个固件时也踩过不少坑,比如U盘格式不对、刷机按键时机没掌握好等等。后来反复尝试了几次,终于摸清了门道。现在我的盒子开机就能看到可爱的萌虎动画,还能用USB无线网卡连接WiFi,彻底摆脱了网线的束缚。 这个固件适合哪些人呢?首先你得有个中兴B863AV3.1-M2的盒子,或者兼容的魔百盒E900V22C/D系列。其次最好有些基础的刷机经验,至少知道怎么进Recovery模式。如果你是纯小白,建议先看看其他基础教程练练手。 2. 萌虎动画的实现原理与定制 2.1 萌虎动画的技术解析 这个固件最吸引人的就是那个虎年主题的开机动画了。我拆解过这个动画包,发现它其实是由一系列PNG图片组成的bootanimation.zip。这个压缩包放在/system/media/目录下,包含三个关键部分: * desc.txt:定义动

By Ne0inhk

开发者入门必看:AI 印象派艺术工坊WebUI集成部署实战推荐

开发者入门必看:AI 印象派艺术工坊WebUI集成部署实战推荐 1. 引言 1.1 业务场景描述 在图像处理与创意设计领域,将普通照片转化为具有艺术风格的画作一直是用户高度关注的功能需求。无论是社交媒体内容创作、数字艺术展示,还是个性化图像服务,一键生成艺术化图像已成为提升用户体验的重要手段。 然而,当前大多数艺术风格迁移方案依赖深度学习模型(如StyleGAN、Neural Style Transfer),存在部署复杂、资源消耗高、启动依赖网络下载等问题,尤其对初学者和轻量级应用场景不够友好。 1.2 痛点分析 传统基于深度学习的图像风格迁移面临以下挑战: * 模型体积大:动辄数百MB甚至上GB的权重文件,增加存储和加载成本。 * 部署门槛高:需要GPU支持、CUDA环境配置,不利于快速验证和本地测试。 * 启动不稳定:依赖外部模型下载,网络波动可能导致服务初始化失败。 * 可解释性差:黑盒模型难以调试,不利于二次开发和算法理解。 1.3 方案预告 本文介绍一个轻量、高效、零依赖的图像艺术化解决方案 —— AI 印象派艺术工坊(Artistic

By Ne0inhk