news 2026/7/5 14:02:25

linux进程间通信------命名管道

作者头像

张小明

前端开发工程师

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

1.命名管道

命名管道FIFO是一种通过文件路径标识的特殊文件,能够为不相关进程提供流式通信能力,任意进程只需要通过统一路径打开该文件即可实现跨进程数据交换其内核缓冲区独立于创建者生命周期存在,但本质仍是无消息边界的单向字节流通道。

1.1创建命名管道

命名管道可以从命令上创建

mkfifo filename

从程序上创建

//int mkfifo(const char* filename,mode_t mode); int main() { mkfifo("h1",0644); return 0; }

mode_t mode是文件掩码用于指定管道权限,规则同open/chmod,实际权限=mode&~umask,能够支持标准宏或自定义八进制值

常用权限

0644所有者读写,其余只读

0600仅所有者读写

0666读写权限最终=0666&~umask

注意mode只控制新建管道的访问权限不含执行权限,

mkfifo函数成功返回0,失败返回-1同时设置errno

1.2匿名管道与命名管道的区别

匿名管道由pipe函数创建并打开

命名管道由mkfifo创建,用open打开

FIFO命名管道与pipe匿名管道之间的唯一区别在于它们创建与打开的方式不同,一旦这些工作完成后就具有相同的语义了

且它们都是单向通道

1.3命名管道的打开方式

当前打开操作为读而打开FIFO时

O_NONBLOCK disable:阻塞直到有进程为写而打开FIFO

O_NONBLOCK enable:立即返回成功

当前打开操作为写而打开FIFO时

O_NONBLOCK disable:阻塞直到有进程为读而打开FIFO

O_NONBLOCK enable:立即返回失败,错误码为ENXIO

2.用命名管道实现文件拷贝

linux内核中规定,FIFO管道必须有读和写两端同时打开,才能正常通信

通过两个进程分别运行不同的程序实现使用命名管道进行文件拷贝

进程A,进行创建命名管道"tp",并以只读的模式打开在当前目录下的普通文件"abc",作为进行拷贝的源文件。

以只写模式打开刚创建的tp管道,后会被阻塞挂起,等待另一个进程B以只读模式打开同一个tp管道,随后将源文件的数据写入tp中。

#include<cstdio> #include<fcntl.h> #include<sys/stat.h> #include<sys/types.h> #include<cstdlib> #include<cerrno> #include<unistd.h> #define ERR_EXIT(m)\ do\ {\ perror(m);\ exit(EXIT_FAILURE);\ }while(0) int main(int argc,char* argv[]) { if(mkfifo("tp",0644)==-1&&errno!=EEXIST) ERR_EXIT("mkfifo"); int infd; infd=open("abc",O_RDONLY); if(infd==-1) ERR_EXIT("open"); int outfd; outfd=open("tp",O_WRONLY); if(outfd==-1) ERR_EXIT("open"); char buf[1024]; ssize_t n; while((n=read(infd,buf,1024))>0) { write(outfd,buf,n); } close(infd); close(outfd); return 0; }

进程B以只写的形式打开当前目录下普通文件abc.bak,O_CREAT|O_TRUNC指的是文件若不存在则创建,若已存在则清空文件内容。

以只读的形式打开已存在的管道tp,此时写端进程A的阻塞会被解除,两端开始进行连接

随后循环不断读取tp管道内的内容写入文件abc.bak,直到管道数据读取完毕也就是收到EOF时,关闭文件描述符,调用unlink删除管道文件tp,清理资源

#include<cstdio> #include<fcntl.h> #include<sys/stat.h> #include<sys/types.h> #include<cstdlib> #include<cerrno> #include<unistd.h> #define ERR_EXIT(m)\ do\ {\ perror(m);\ exit(EXIT_FAILURE);\ }while(0) int main(int argc,char* argv[]) { int outfd; outfd=open("abc.bak",O_WRONLY|O_CREAT|O_TRUNC,0644); if(outfd==-1) ERR_EXIT("open"); int infd; infd=open("tp",O_RDONLY); if(infd==-1) ERR_EXIT("open"); char buf[1024]; ssize_t n; while((n=read(infd,buf,1024))>0) { write(outfd,buf,n); } close(infd); close(outfd); unlink("tp"); return 0; }

3.使用命名管道实现客户端与服务器端通信

这是一个基于命名管道FIFO单向通信服务端,其设计为单客户端模式,单次运行仅负责接收一个客户端所发的消息,并且引入了信号处理机制,通过捕捉信号SIGINT信号也就是ctrl+c,可以确保用户强行中断进程时,能够自动清理残留的管道文件tp

客户端

#include<iostream> #include<cstring> #include<fcntl.h> #include<cerrno> #include<unistd.h> using namespace std; #define ERR_EXIT(m)\ do\ {\ perror(m);\ exit(EXIT_FAILURE);\ }while(0); int main() { int wfd=open("tp",O_WRONLY); if(wfd==-1) ERR_EXIT("open"); char buf[1025]; cout<<"please wait..."<<endl; while(1) { fflush(stdout); ssize_t n=read(0,buf,sizeof(buf));//read会从buf[0]开始写 if(n>0) { buf[n]=0; ssize_t s=write(wfd,buf,n); if(s<0) ERR_EXIT("write"); } else if(n==0) { break; } else { ERR_EXIT("read"); } } if(close(wfd)==-1) ERR_EXIT("close"); return 0; }

服务器端

#include<iostream> #include<cstring> #include<fcntl.h> #include<cerrno> #include<unistd.h> #include<signal.h> #include<sys/types.h> #include<sys/stat.h> using namespace std; #define ERR_EXIT(m)\ do\ {\ perror(m);\ exit(EXIT_FAILURE);\ }while(0); const char* file_name="tp"; void clean_and_exit(int sig) { unlink(file_name); _exit(0); } int main() { umask(0); unlink(file_name);//删除同名文件 if(mkfifo(file_name,0644)==-1) ERR_EXIT("mkfifo"); //注册信号处理函数,处理使用ctrl+c发送结束进行的信号 signal(SIGINT,clean_and_exit); int rfd=open(file_name,O_RDONLY); if(rfd<0) ERR_EXIT("open"); char buf[1024]; cout<<"please wait..."<<endl; while(1) { ssize_t n=read(rfd,buf,sizeof(buf)); if(n>0) { cout<<"client says# "; cout.write(buf,n);//按精度长度输出,避免越界 } else if(n==0) { cout<<"client disconnected"<<endl; break; } else { if(errno==EINTR) continue; ERR_EXIT("read"); } } close(rfd); unlink(file_name); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 14:01:57

Python 里的 `‘‘.join(sorted(s))` 到底是什么意思?

刷 LeetCode 的时候&#xff0c;经常会看到这样一行代码&#xff1a; key .join(sorted(s))第一次看到这行代码&#xff0c;很多人都会愣一下&#xff1a; “这什么东西&#xff1f;空字符串、join、sorted&#xff0c;怎么还三件套组合技&#xff1f;” 别急&#xff0c;这行…

作者头像 李华
网站建设 2026/7/5 14:01:38

别再瞎更新了!用数据可视化把账号做起来(实验7-3)

一、实验目的本实验基于实验7-1和实验7-2输出的数据表&#xff0c;使用助睿BI完成多维度可视化探索。实验重点是通过指标卡、排名图、标题影响分析图和趋势图&#xff0c;对自媒体作品运营效果进行展示与解释&#xff0c;并最终形成综合仪表盘。本实验使用三张数据表构建数据集…

作者头像 李华
网站建设 2026/7/5 14:00:49

数据操作+数据预处理

数据 1.张量&#xff08;tensor&#xff09; 其实就是n维数组&#xff0c;在PyTorch和TensorFlow中张量类为Tensor&#xff0c;是深度学习主要的数据结构。 0维——标量 1维——向量 2维——矩阵&#xff0c;每一行表示一个样本&#xff0c;每一列表示特征 3维——图片&#xf…

作者头像 李华
网站建设 2026/7/5 14:00:13

一键部署言埠 YanPub Docker:万言归埠,一站集成。Adapter Quality CI中文编程语言统一基础设施。一个框架,接入任意中文语言,即刻获得完整工具链。

言埠 YanPub 万言归埠&#xff0c;一站集成。 中文编程语言统一基础设施。一个框架&#xff0c;接入任意中文语言&#xff0c;即刻获得完整工具链。 AtomGit - 全球开发者的开源社区,开源代码托管平台 Docker 一键部署 从 gitcode 拿到 yanpub 后&#xff0c;三步即可启动含 …

作者头像 李华
网站建设 2026/7/5 13:58:12

VLA-Adapter论文解读(五):实验分析

论文链接&#xff1a;[2509.09372] VLA-Adapter: An Effective Paradigm for Tiny-Scale Vision-Language-Action Model 项目主页&#xff1a;VLA-Adapter 前言&#xff1a;本文拆解了VLA-Adapter实验的研究方法论和架构设计&#xff0c;覆盖了模拟基准测试、消融实验、真实机…

作者头像 李华
网站建设 2026/7/5 13:57:29

Python sort函数参数藏大招!用错它,你的代码直接废了

排序这个操作作为其中的一个基本操作, 该语言给出了两种主要的数据排序办法: sort&#xff08;&#xff09;以及&#xff08;&#xff09;, 虽说两者都是用以按特定顺序去排列数据, 然而它们展开工作的方式存在稍许不同, 且应用于不一样的场景, 弄明白sort&#xff08;&#xf…

作者头像 李华