Linux下进程间的通信--管道
关于进程间的通信
Linux进程间通信(Inter-Process Communication,IPC)是指在多个进程之间传输数据或信号的一些方法。由于Linux中的进程有各自独立的地址空间,因此它们不能直接访问对方的内存。为了实现进程间的通信,Linux提供了多种机制:管道,信号,消息队列,共享内存,网络
Linux下的进程通信手段基本上是从Unix平台上继承而来的
进程间通讯分为单个计算机的进程间通讯和局域网的进程间通讯
管道
管道简介:
管道是一种最基本的IPC机制,它允许一个进程的输出成为另一个进程的输入。管道是半双工的,数据只能向一个方向流动
管道的本质:是操作系统内核提供的一种进程间通信机制,它通过内核缓冲区和文件描述符来实现进程间的数据交换和同步
管道分为无名管道与有名管道
一.无名管道
无名管道的特点:
无名管道只能实现单向通信,数据只能从一端流向另一端
无名管道通常用于父子进程之间的通信,因为它们需要在创建时就确定通信的两端
无名管道没有名字,它们在文件系统中不可见,仅在创建它们的进程及其子进程的生命周期内存在。
无名管道将读端与写端抽象成两个文件进行操作,在无名管道创建成功之后,则会返回将读端与写端的文件描述符存入数组
创建无名管道
pipe()函数
函数描述:pipe()创建了一个管道,这是一种单向数据通道,可用于进程间通信。数组 pipefd 用于返回指向管道两端的两个文件描述符。pipefd[0]`指向管道的读端,pipefd[1] 指向管道的写端。写入管道写端的数据将由内核缓冲,直到从管道读端读取。
函数头文件
#include <unistd.h> 功能
管道创建之后,内核会将文件描述符存储到数组 函数原型
int pipe(int pipefd[2]);函数参数
pipefd:用于存储无名管道读端与写端的文件描述符的数组
pipefd[0]:读端文件描述符
pipefd[1]:写端文件描述符 函数返回值:
成功:0
失败:-1,设置 errno,同时将pipefd保持不变
示例代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>int main()
{int pipefd[2];int num=pipe(pipefd);if(num == -1){perror("pipe\n");exit(EXIT_FAILURE);}pid_t pid = fork(); // 创建子进程if (pid == -1){perror("fork failed");return 1;}else if (pid == 0){close(pipefd[1]);char buffer[64];size_t rbytes = read(pipefd[0],buffer,sizeof(buffer));if(rbytes == -1){perror("read fail\n");close(pipefd[0]);}else{printf("read : %s\n",buffer);close(pipefd[0]);}}else{close(pipefd[0]);char buf[128]={0};printf("please to input information\n");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';size_t wbytes = write(pipefd[1],buf,sizeof(buf));if(wbytes==-1){perror("write fail\n");close(pipefd[1]);}else{printf("wbytes = %ld\n",wbytes);close(pipefd[1]);}}waitpid(-1,NULL,0);return 0;
}
代码解读:
使用pipe
函数创建一个无名管道,并将文件描述符数组pipefd
的两个元素分别设置为管道的读端和写端。如果创建失败,打印错误信息并退出
调用fork
函数创建子进程。如果fork
失败,打印错误信息并返回1。
如果pid
为0,说明当前是子进程。关闭管道的写端文件描述符。
定义一个字符数组buffer
,用于存储从管道读取的数据。
从管道的读端读取数据到buffer
。如果读取失败,打印错误信息并关闭读端文件描述符。如果读取成功,打印读取的内容并关闭读端文件描述符。
如果pid
不为0,说明当前是父进程。关闭管道的读端文件描述符。
定义一个字符数组buf
,用于存储用户输入的数据。
将用户输入的数据写入管道的写端。如果写入失败,打印错误信息并关闭写端文件描述符。如果写入成功,打印写入的字节数并关闭写端文件描述符。
调用waitpid
函数等待子进程结束。-1
表示等待任意子进程,NULL
表示不需要子进程的终止状态,0
表示不设置任何选项。
二.有名管道
有名管道的特点:
有名管道在文件系统中以文件的形式存在,但不占用磁盘空间,即使创建它的进程已经退出,有名管道仍然存在,直到被显式删除。
有名管道允许任何知道管道名称的进程进行通信
有名管道提供了一种同步机制,写入操作在管道有足够空间时才会成功,读取操作在管道中有数据时才会成功
创建有名管道
mkfifo
命令
mkfifo [选项]... 名字
-m
或--mode=模式
:设置创建的有名管道的权限。如果不设置,将使用默认的权限(通常是 0666,即允许所有用户读写)。-p
或--fifo=路径
:指定有名管道的路径。如果路径不存在,mkfifo
会创建它。
mkfifo()
系统调用
函数描述:
mkfifo()创建一个名为pathname的FIFO特殊文件。mode指定FIFO的权限。它由进程的umask以通常的方式修改:创建的文件的权限是(mode & ~umask)。
FIFO特殊文件类似于管道,只是其创建方式不同。通过调用mkfifo()将FIFO特殊文件输入到文件系统中,而不是作为匿名通信通道。
一旦你以这种方式创建了一个FIFO特殊文件,任何进程都可以打开它进行读写,就像普通文件一样。但是,在您可以对其进行任何输入或输出操作之前,它必须同时在两端打开。为读打开FIFO通常会阻塞,直到其他进程为写打开相同的FIFO,反之亦然。
函数头文件
#include <sys/types.h>
#include <sys/stat.h>函数原型:
int mkfifo(const char *pathname, mode_t mode);函数参数:
pathname:有名管道路径名
mode:有名管道文件访问权限, 常用0644函数返回值:
成功:返回0
失败:返回-1,并设置errno
示例代码:
进程A:
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PATH "/home/linux/namepipe"
int main()
{int fr = open(PATH,O_RDONLY);if(fr==-1){perror("open fail");exit(EXIT_FAILURE);}char buffer[128];ssize_t rbytes = read(fr,buffer,sizeof(buffer));if(rbytes==-1){perror("read fail");close(fr);exit(EXIT_FAILURE);}printf("rbytes=%ld buffer=%s\n",rbytes,buffer);close(fr);return 0;
}
进程B:
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>#define PATH_NAME "/home/linux/npipe"
int main()
{int result = access(PATH_NAME,F_OK);if(result == -1){int ret = mkfifo(PATH_NAME,0666);if(ret==-1){perror("mkfifo:");exit(EXIT_FAILURE);}}int fw = open(PATH_NAME,O_WRONLY);if(fw==-1){perror("open:");exit(EXIT_FAILURE);}char buf[128]={0};printf("please to enter\n");fgets(buf,sizeof(buf),stdin);buf[strlen(buf)-1]='\0';ssize_t wbytes = write(fw,buf,sizeof(buf));if(wbytes==-1){perror("write:");close(fw);exit(EXIT_FAILURE);}printf("wbytes=%ld buf=%s\n",wbytes,buf);close(fw);return 0;
}
代码解读:
进程B:
用于从有名管道(FIFO)中写入数据
定义有名管道的路径宏PATH_NAME
。
使用access
函数检查有名管道是否存在。F_OK
是access
函数的参数,用于检查文件是否存在。
如果有名管道不存在,使用mkfifo
函数创建它。如果创建失败,使用perror
打印错误信息,然后退出程序。
以只写模式(O_WRONLY
)打开有名管道。如果打开失败,使用perror
打印错误信息,然后退出程序。
定义一个字符数组buf
,用于存储用户输入的数据。
使用fgets
函数从标准输入读取一行数据到buf
。fgets
会读取直到换行符或缓冲区满,但不包括换行符。
将buf
数组中的最后一个字符(换行符)替换为字符串结束符\0
。
使用write
函数将用户输入的数据写入有名管道。如果写入失败,使用perror
打印错误信息,关闭文件描述符fw
,然后退出程序。
关闭文件描述符fw
。
进程A:
用于从有名管道(FIFO)中读取数据
使用open
函数以只读模式(O_RDONLY
)打开有名管道。如果打开失败,open
函数返回-1。
如果open
函数失败,使用perror
打印错误信息,然后退出程序。
定义一个字符数组buffer
,用于存储从有名管道读取的数据。
使用read
函数从有名管道中读取数据到buffer
。如果读取失败,read
函数返回-1。
如果read
函数失败,使用perror
打印错误信息,关闭文件描述符fr
,然后退出程序。
关闭文件描述符fr
。
结语:
无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力
相关文章:

Linux下进程间的通信--管道
关于进程间的通信 Linux进程间通信(Inter-Process Communication,IPC)是指在多个进程之间传输数据或信号的一些方法。由于Linux中的进程有各自独立的地址空间,因此它们不能直接访问对方的内存。为了实现进程间的通信,…...
【算法】汉诺塔、顺序查找和二分查找法、冒泡排序、插入排序、选择排序
1 时间装饰器 2 汉诺塔 3 顺序查找和二分查找法 4 冒泡排序 5 插入排序 6 选择排序 1 时间装饰器 import timedef cal_time(func):def wrapper(*args, **kwargs):t1 time.time()result func(*args, **kwargs)t2 time.time()print("%s running time: %s secs." % …...

Mac电脑遇到DNS解析失败,ip可以访问,域名无法访问
当Mac电脑遇到DNS解析失败的问题时,可以尝试以下几个解决方法: 1.检查网络连接:确保Mac已连接到可用的网络,并且网络连接正常。可以尝试重新连接Wi-Fi或使用有线连接来排除网络问题。 2.清除DNS缓存:打开终端应…...

走进 “星星的孩子” 的世界:理解与关爱儿童自闭症
在这个充满生机与活力的世界里,有一群特殊的孩子,他们仿佛来自遥远的星球,沉浸在自己的独特世界中,难以与外界进行有效的沟通和互动。他们是自闭症儿童,也被称为 “星星的孩子”。 自闭症,又称孤独症谱系障…...

【学习笔记】7、存储器、复杂可编程器件和现场可编程门阵列
可编程逻辑器件PLD复杂可编程逻辑器件CPLD现场可编程门阵列FPGA 7.1 只读存储器(ROM) 7.1.1 ROM的结构 ROM存储器 存储阵列 地址译码器 输出控制电路 存储阵列,由许多存储单元(1bit)组成。每次读出一组数据&…...
Java面试题———RabbitMQ篇
目录 1.你们项目中哪里用到了RabbitMQ 2、为什么会选择使用RabbitMQ 3、使用RabbitMQ如何保证消息不丢失 4、消息的重复消费问题如何解决的 5、如何解决消息堆积在MQ的问题 6、RabbitMQ如何保证消费的顺序性 7、RabbitMQ的延迟队列有了解过嘛 8、RabbitMQ如何设置消息过…...

2 种方式申请免费 SSL 证书,阿里云 Certbot
如何使用免费的 SSL 证书,有时在项目中需要使用免费的 SSL 证书,Aliyun 提供免费证书,三个月有效期,可以直接在aliyun 申请,搜索 SSL 证书,选择测试证书。 Aliyun 证书需要每三月来来换一次,页…...
49.给出一个字符串数组,实现一个算法给定一组字符串,将字母异位词组合在一起
49. Group Anagrams 题目 给定一组字符串,将字母异位词组合在一起。 示例: 输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [ [“ate”,“eat”,“tea”], [“nat”,“tan”], [“bat”] ] 注意: 所有输入均为小写字母。输出的顺序可以…...

如何制作统信UOS启动盘?
如何制作统信UOS启动盘? 一、下载UOS系统安装镜像二、在UOS系统环境下制作启动盘步骤一:准备U盘步骤二:打开启动盘制作工具步骤三:选择ISO镜像文件步骤四:选择安装介质并格式化步骤五:等待制作完成 三、在W…...
Conda命令
查看当前有哪些虚拟环境 conda env list创建(删除)一个新的虚拟环境 conda create --name test1 python3.8 conda env remove --name test1进入和退出一个环境 conda activate test1 conda deactivate列出当前包安装的包 conda list安装包 conda in…...
perl——获取数组中元素的索引
参考: 如何获取数组中元素的索引 如果保证所有元素都是唯一的,或者只有第一个索引是感兴趣的: my ($index) grep { $array[$_] ~~ $element } 0 .. $#array;...
Vector vs 数组:Java中Vector相比数组的优点
每日自动更新各类学习教程及工具下载合集 https://pan.quark.cn/s/874c74e8040e 在Java编程中,数组(Array)和Vector都是用于存储数据的容器,但它们在设计和功能上有所不同。选择使用哪种数据结构取决于具体的需求。在这…...
掌握步进电机控制算法:提升自动化精度的关键(代码示例)
引言 步进电机因其高精度定位、良好的控制性能和简单的驱动方式,广泛应用于各类自动化设备中,如3D打印机、数控机床和机器人等。为了实现对步进电机的精确控制,采用合适的控制算法至关重要。本文将详细介绍几种常见的步进电机控制算法&#…...

MySQL的源码安装及基本部署(基于RHEL7.9)
这里源码安装mysql的5.7.44版本 一、源码安装 1.下载并解压mysql , 进入目录: wget https://downloads.mysql.com/archives/get/p/23/file/mysql-boost-5.7.44.tar.gz tar xf mysql-boost-5.7.44.tar.gz cd mysql-5.7.44/ 2.准备好mysql编译安装依赖: yum install cmake g…...

RUP-系统架构师(五十六)
1在RUP中采用“41”视图模型来描述软件系统的体系结构。在该模型中,最终用户侧重于(),系统工程师侧重于()。 问题1 问题2 A 实现视图 B 进程视图 C 逻辑视图 D 部署视图 解析: RUP有 逻辑…...

【大模型系列篇】人工智能与智能计算的发展
🔥🔥🔥 来自 中国工程院院士、中国科学院计算技术研究所研究员 孙凝晖 第十四届全国人大常委会专题讲座上的讲稿《人工智能与智能计算的发展》 “把新一代人工智能作为推动科技跨越发展、 产业优化升级、生产力整体跃升的驱动力量,…...

C++ | Leetcode C++题解之第365题水壶问题
题目: 题解: class Solution { public:bool canMeasureWater(int x, int y, int z) {if (x y < z) {return false;}if (x 0 || y 0) {return z 0 || x y z;}return z % gcd(x, y) 0;} };...

c++-类(中)
c-类(中) 一、类的默认成员函数1.1 什么是默认成员函数?1.2 默认成员函数有哪些? 二、构造函数2.1 什么是构造函数?2.2 构造函数的特点 三、析构函数3.1 什么是析构函数?3.2 析构函数的特点 四、拷贝构造函…...
在 Python 中查找列表中的重复元素
在 Python 中查找列表中的重复元素 在数据处理和分析中,查找重复元素是一个常见的任务。无论是在数据清洗、用户输入验证还是统计分析中,识别和处理重复数据都是至关重要的。在 Python 中,有多种方法可以查找列表中的重复元素。本文将详细介绍这些方法,包括示例代码、性能…...

Kafka【一】Windows下安装单节点Kafka
① 下载 下载软件安装包:kafka_2.12-3.6.1.tgz,下载地址:https://kafka.apache.org/downloads 这里的3.6.1,是Kafka软件的版本。截至到2023年12月24日,Kafka最新版本为3.6.1。2.12是对应的Scala开发语言版本。Scala2…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

Mysql中select查询语句的执行过程
目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析(Parser) 2.4、执行sql 1. 预处理(Preprocessor) 2. 查询优化器(Optimizer) 3. 执行器…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...