linux下的进程间通信-管道及共享内存
进程间通信(IPC):操作系统为用户提供的集中进程间通信方式;
为什么要进程间通信?
进程之间具有独立性(每个进程有自己的虚拟地址空间),访问自己的虚拟地址,无法访问同一块区域,因此无法实现数据通信。
针对不同的通信场景提供多种通信方式:数据传输-管道/消息队列;数据共享-共享内存;进程控制-信号量。
管道:本质:内核中的一块缓冲区;多个进程若访问同一个管道(一块缓冲区)可实现通信;
种类:匿名管道/命名管道
匿名管道:内核中的缓冲区没有具体的标识符;只能用于亲缘关系的进程间通信;
原因:只能通过子进程复制父进程的方式获取管道的操作句柄;父进程创建管道的时候操作系统会返回管道的操作句柄(文件描述符)。
如何创建匿名管道?
int pipe(int pipefd[2]);pipefd[2]--具有两个int型节点的数组的首地址,用于接收创建管道返回的操作句柄。
pipefd[0]-用于管道中读取数据;pipefd[1]-用于向管道中写入数据。
管道是一个单向的资源传输,自身并不确定资源的传输方向;管道是一个半双工通信(可选择方向的单向传输)
返回值:成功返回0,失败返回错误代码。
子进程打印的信息,打印到了shell提示信息的后边:父进程先于子进程退出,子进程成为孤儿进程运行在后台。子进程后台运行时,shell切换回到前台打印提示信息,然后子进程打印信息就会打印到提示信息后边。
父进程创建了子进程,谁先运行不一定,取决于cpu的调度。
管道的读写特性:
1.若管道中没有数据,则调用read读取数据会阻塞,进程暂停执行。
2.若管道中数据满了,则调用write写入数据会阻塞;管道是一块缓冲区(内存空间),并非无限制大
阻塞:为了完成一个功能,发起调用,若当前不具备完成条件,则一直等待。
如下:
结果如下:管道是一块缓冲区,并非无限制大。
3.若管道的所有读端pipefd[0]被关闭,则继续调用write会产生异常导致进程退出。
关闭所有读端,会发生程序发生异常,直接退出。
4.若管道的所有写端pipefd[1]被关闭,则继续调用read,读完管道中的数据后不再阻塞,而是返回0.
关闭所有写端,程序读取不到数据。
我们写的程序大多都是守护进程,是一种特殊的孤儿进程,孤儿进程不危险,危险的是僵尸进程。
通过匿名管道实现命令行中管道符的作用:ps -ef |grep ssh
ps -ef:默认讲结果打印到标准输出 grep ssh:默认从标准输入读取数据进行过滤
ps进程如何将输出结果,并不写入标准输出而是写入到管道中呢??将标准输出重定向管入道写端
grep进程如何做到不从标准输入读取数据,而是从管道读取数据呢??将标准输入重定向管道写入端。
grep过滤了结果后并不会退出,循环读取数据进行过滤,因此ps进程退出后需要关闭所有写端,没有数据可写了。
结果如下:
命名管道:内核中的缓冲区,具有标识符,标识符是一个可见于文件系统的管道文件,能够被其他进程找到并打开管道文件则可以获取管道的操作句柄。---可用于同一主机上的任意进程间通信
打开2个端口,可以进行2个端口间的进程间通信,一方打印出来,另一方退出。
多个进程通过命名管道通信是通过打开命名管道文件访问同一块内核中的缓冲区实现通信
可通过:mkfifo 创建管道文件
代码中的操作:int mkfifo(char *filename,mode_t mode);
filename:管道文件名称; mode;管道文件权限;成功返回0;失败返回-1
剩下的操作与文件IO操作雷同
open打开命名管道特性:若文件以只读打开,则会阻塞,直到文件被以写的方式打开
若文件以只写打开,则会阻塞,直到文件被以读的方式打开
vnew ./fifo_write.c同时打开这个进程,gg-y-G-P把一个vi程序全文复制粘贴到另一个ci中。
总结:管道本质:内核中一块缓冲区
分类:匿名管道-具有亲缘关系的进程间通信
命名管道-用于同一主机上的任意进程间通信
特性:1.管道是半双工通信(可选择方向的单向传输)
2.管道读写特性(匿名和命名管道一样)
若管道中没有数据则read阻塞;若管道中数据满了则write阻塞;
若管道所有读端关闭则write会触发异常;若管道所有写端关闭则read读完数据返回0,不再阻塞。
3.管道生命周期随进程(打开管道的所有进程退出,管道就会被释放(命名管道一样,本质都是缓冲区,文件只是标识符))
4.管道提供字节流传输服务(可靠的,有序的,基于连接的一种灵活性比较高的传输)
5. 命名管道额外有一个打开特性:
若文件以只读打开,则会阻塞,直到文件被以写的方式打开
若文件以只写打开,则会阻塞,直到文件被以读的方式打开
6.管道自带同步与互斥
同步:通过条件判断实现临界资源操作的合理性
互斥:通过唯一访问实现临界资源操作的安全性
共享内存:
特性:共享内存是最快的进程间通信方式
本质原理:在物理内存上开辟一块空间,多个进程可以将同一块物理内存空间映射到自己的虚拟地址空间,通过自己的虚拟地址直接访问这块空间,通过这种方式实现数据共享。
管道通信中:涉及到两次用户态和内核态之间的数据拷贝;将数据写入管道,从管道读取数据
共享内存的通信:直接通过虚拟地址访问物理内存实现共享内存中的数据操作,速度最快。
共享内存的生命周跟随内核,在物理内存开辟空间,信息存储在内核;共享内存是属于内核的一个进程间通信资源;不会随着进程的退出而释放;内核重启会释放或者手动释放,否则一直存在于内核。
共享内存的操作流程:
1.创建共享内存--在物理内存上开辟空间
int shmget(key_t key, size_t size, int shmflg);
key:内核中共享内存的标识符--多个进程通过相同的标识符才能打开同一个共享内存
size:共享内存大小--以内存页为单位进行分配
shmflg:IPC_CREAT-存在则打开,不存在则创建|IPC_EXCL-与IPC_CREAT同时使用,若存在则报错,不存在则创建|mode
返回值:返回一个非负整数--共享内存的操作句柄,失败返回-1.
生成一个key值,key_t ftok(const char *pathname,int proj_id);--通过inode节点号与projid合成一个key。
2.进程将共享内存映射为到自己虚拟地址空间
void *shmat(int shmid, const void *shmaddr, int shmflg);
shmid:shmget返回的共享内存操作句柄
shmaddr:共享内存映射在虚拟地址空间中的首地址--通常置NULL
shmflg:映射成功之后对共享内存可进行的操作, SHM_RDONLY用于只读(前提是有读的权限)/0-默认可读可写
返回值:返回共享内存映射在虚拟地址空间中的首地址--通过这个首地址进行后续的内存操作。失败返回-1(void*)-1
3.基本的内存操作都可以对这块空间进行操作
int shmdt(const void *shmaddr);
shmaddr:映射在虚拟地址空间中的首地址,成功返回0,失败返回-1
4.解除虚拟地址空间与共享内存的映射关系
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
shmid:共享内存操作句柄
cmd:对共享内存想要进行的操作 IPC_RMID-删除共享内存
buf:用于获取/设置共享内存信息的结构,不适用则置NULL
成功返回0;失败返回-1;
5.释放共享内存资源
进程间通信资源的命令操作:
操作命令:ipcs 查看所有的进程间通信资源
ipcs -m 查看共享内存进程间通信
ipcs -q 查看消息队列进程间通信
ipcs -s 查看信号量进程间通信
ipcrm -m id:删除进程间通信资源
共享内存删除的时候,并不会立即被删除,只是将其状态置为被销毁状态,移除标识,--为了不让这个共享内存继续被其他进程映射连接,然后等到当前共享内存映射连接数为0的时候,才会真正删除这块共享内存。
共享内存数据的写入,是一种针对地址指向空间的覆盖式写入。
共享内存:本质原理:多个进程将同一块物理内存映射到自己的虚拟地址空间实现数据共享
特性:
1.最快的进程间通信方式
2.生命周期随内核
注意:共享内存并没有自带同步与互斥--多个进程进行访问的时候存在安全问题
操作:代码操作流程/具体接口+命令操作ipcs/ipcrm
管道pipefd是传输数据,共享内存主要用于数据共享
管道生命周期随进程,共享内存生命周期随内核
linux下的进程间通信-管道及共享内存相关推荐
- Linux下使用awk批量删除共享内存
1.awk简介 awk 是一个强大的文本分析工具.sed 常常用于一整个行的处理,而 awk 则倾向于以空格和tab键为默认分隔符将每行切片成一个个域(也就是一列)来处理.awk适用于小型的数据处理. ...
- 【Linux学习】进程间通信——system V(共享内存 | 消息队列 | 信号量)
- 进程间通信(匿名管道、命名管道、共享内存)
进程间通信 进程间通信的作用 管道 匿名管道 命令感受匿名管道 从内核角度去解释匿名管道 代码创建匿名管道 从PCB角度去分析匿名管道 匿名管道的非阻塞读写特性 创建管道,获取管道读写两端文件描述符的 ...
- linux 服务器间通信,Linux 下的进程间通信:套接字和信号 | Linux 中国
原标题:Linux 下的进程间通信:套接字和信号 | Linux 中国 学习在 Linux 中进程是如何与其他进程进行同步的. -- Marty Kalin 本篇是 Linux 下(IPC)系列的第三 ...
- Linux系统中消息队列,共享内存、信号和线程的基本操作使用方法
Linux系统中消息队列,共享内存.信号和线程高级操作 第十一章 消息队列 10.1消息队列定义 10.2 消息队列特点 10.3 key值 10.4 创建消息队列 10.4.1 发送消息 10.4. ...
- java 收集系统资源_方法:Linux 下用JAVA获取CPU、内存、磁盘的系统资源信息
CPU使用率: InputStream is = null; InputStreamReader isr = null; BufferedReader brStat = null; StringTok ...
- Linux下构建自己的C++共享库并配合pkg-config生成链接选项
Linux下构建自己的C++共享库并配合pkg-config生成链接选项 本文将以C++链表的新建.打印操作为例构建自己的共享库,并在实际调试代码时尝试使用.我们在做数据结构题时经常需要将链表打印出来 ...
- linux下查看服务器的cpu、内存大小、硬盘大小
linux下查看服务器的cpu.内存大小.硬盘大小 今天查服务器硬件情况,上网搜到了这篇文章,感觉很好,自己定个坐标. 我看的原文地址 https://www.cnblogs.com/li-shuai ...
- linux 下通过smbclient访问windows共享目录
linux 下通过smbclient访问windows共享目录 sudo apt-get install samba #---------------------------------------- ...
最新文章
- Django入门之开发环境搭建1.1
- Node:非IO的异步API
- Super BOM应用步骤总结
- 7-26晚上实现mystring
- 三层交换(VLAN间互通+路由功能)+VTP+STP(PVST)综合实验(理论+实践=真实)
- typora+picgo+gitee搭建免费图床纵享丝滑
- VSCode详细安装教程
- 关于ecshop模板更新版本的解决方法(三)
- C#-老生常谈的 值类型与引用类型
- Signaltap的使用
- JSP技术之JavaBean
- Window系统下搭建GIT本地服务器详细教程
- bootstrap table 合并行_elementUI表格合并
- PS CC 2014使用到期解决方法,其他类似
- scrapy爬取动态网页
- vue3代码检查以及格式化配置
- 《大学物理》课程考试大纲
- js如何给php传图片,JavaScript怎么上传图片
- 8255A红绿灯c语言程序,汇编语言的交通灯程序
- 开源社区“大牛”关于“开源”的大讨论
热门文章
- 异常检测2——PCA异常检测
- pandas dataframe对多列同时排序
- java解决Exception in thread “main“ java.lang.OutOfMemoryError: GC overhead limit exceeded
- 和push的区别_RocketMQ的消息订阅push和pull的区别
- Linux Hung Task分析
- Linux 系统之Sysvinit
- 基于QQ服务器JavaMail邮箱SSL密码第三方发送邮件
- Swift-EasingAnimation
- STM32L之可编程电压检测(PVD)
- KlayGE C++代码风格指南英文版