本文主要是介绍操作系统-进程间的四种通信(共享内存、消息队列、信号、管道),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
进程间通信
文章目录
- 进程间通信
- 共享内存
- 消息队列
- 信号
- 信号的接收处理
- 内核对于信号的基本处理办法
- 管道通信
- 无名管道
- 有名管道
进程间的通信有三种基本的模型,共享内存和消息传递和管道。
- 共享内存模型会建立起一块协作进程的共享的内存区域,进程通过向共享区域读入或写入数据来交换信息
- 消息传递模型通过在协作进程间交换信息来实现通信
共享内存
共享内存区是最快的(进程间通信)IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
注意:共享内存没有进行同步与互斥!共享内存不会自动销毁,要手动销毁。
共享内存的原理图 --学习进程前先学习一下内存管理效果感觉更好 -内存管理部分我以己经学完,所以理解的比较轻松,内存管理部分后边我也会在学习一遍,也会有笔记发布在我的博客上。
了解关于共享内存的接口以及示例可访问下面链接:
https://blog.csdn.net/2202_75305885/article/details/136240275
采用共享内存进行进程间通信,需要通信进程简建立共享内存区域
通常,一片共享内存区域驻留在创建共享内存的进程地址空间内,其他希望使用这个共享内存段的进行通信的进程应将其附加到自己的地址空间。
通常操作系统会试图阻止一个进程访问另一个进程的内存,共享内存需要两个或更多的进程同意取消这一限制。
他们希望通过共享区域内读出或者写入来交换信息,数据的类型或者位置取决于这些进程,而不是受控于操作系统。另外通信的进程需要确保,他们不会向同一位置写入数(可以用同步与互斥来确保)
消息队列
消息队列是有操作系统维护的以字节序列为基本单位的间接通信机制
- 每个消息是一个字节序列
- 相同标识的消息组成按先进先出的顺序组成一个消息队列
消息队列的系统调用
信号
软中断信号(signal,简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
进程间的软件中断通知和处理机制,如SIGKILL,SIGSTOP、SIGSTOP等
- 操作系统在编译你的程序的时候,会缺省的加上对于这些信号的处理例程。
信号的接收处理
- 捕获(catch):执行进程指定的信号处理函数被调用
- 忽略(Ignore):执行操作系统指定的缺省处理。
- 例如:进程终止、进程挂起等
- 屏蔽(Mask):禁止进程接受和处理信号
缺点:
传送的信息量小,只有一个信号类型
信号的实现
内核对于信号的基本处理办法
-
Linux内核给一个进程发送信号的方法是,在进程所在的进程表项的信号域设置对应于该信号地位,
-
内核处理一个进程收到的信号的时机是在一个进程从内核态返回用户态时。所以,当一个进程在内核态下运行时,软中断信号并不立即起作用,要等到将返回用户态时才处理。进程只有处理完信号才会返回用户态,进程在用户态下不会有未处理完的信号。
-
内核处理一个进程收到的软中断信号是在该进程的上下文中,因此,进程必须处于运行状态
-
如果进程收到一个要捕捉的信号,那么进程从内核态返回用户态时执行用户定义的函数。而且执行用户定义的函数的方法很巧妙,内核是在用户栈上创建一个新的层,该层中将返回地址的值设置成用户定义的处理函数的地址,这样进程从内核返回弹出栈顶时就返回到用户定义的函数处,从函数返回再弹出栈顶时, 才返回原先进入内核的地方。这样做的原因是用户定义的处理函数不能且不允许在内核态下执行(如果用户定义的函数在内核态下运行的话,用户就可以获得任何权限)。
此处内容摘自 https://baike.baidu.com/item/%E4%BF%A1%E5%8F%B7/7927794?fr=ge_ala 只是摘录部分,全部内容可前往链接
管道通信
进程间基于内存文件的通信机制
- 也就是说,如果两个进程要使用管道通信,内核会在内存中创建一块内存,只要多个进程能访问到这块内存就可以了
- 管道其实就是操作系统内核中的一块缓冲区
- 一次只允许一个进程使用的资源,称为临界资源。管道在同一时刻只允许一个进程对其进行写入或是读取操作,因此管道也就是一种临界资源。而临界资源需要保护,内核也管道文件提供了同步和互斥的功能
无名管道
- 只能用于具有亲缘关系的进程,像父子进程、兄弟进程、祖孙进程、叔侄进程。其中,指令中的竖线,ps aux | grep,是兄弟关系,因为ps和grep的父进程都是bash。。
- 半双工,在需要双方进行通信的时候,需要建立起两个管道。
- **进程退出,管道释放。这里的进程是指持有管道的最后一个进程。**当然,你也可以选择将所有进程手动关闭掉那两个文件描述符。
- 内核会对管道(匿名/命名管道)进行同步与互斥。- 无名管道的大小一般是64K
- 无名管道默认是阻塞模式
无名管道只能在血缘的进程间通信的原因:
无名管道通信指的是多个进程在内核申请的管道文件进行通信,这就需要所有进程能够知道这个申请成功管道文件的读写文件描述符,有亲缘关系的进程可以在分离进程之前在内核空间申请管道文件,在分离进程后所有有亲缘关系的进程都能通过复制的文件描述符访问同系统文件表,进而访问一个管道文件的地址,因此无名管道只适用于有亲缘的进程之间的通信
有名管道
在内核中这块缓冲区是有标识的,意味着所有的进程都可以通过这个标识找到这块缓冲区进行通信,也就是命名管道可以用于同一主机上的任意进程进行通信。
命名管道的标识实际上是一个文件,可见于文件系统,意味着所有进程都可以通过打开文件进而访问到内核中的缓冲区。
特性:
- 半双工
- 面向字节流,读写非常灵活
- 有名管道在文件系统中具有唯一的路径名,可以通过路径名进行访问和引用
- 同步与互斥
- 可以是任意进程间的通信
- 进程退出,内核中的内存也就释放了,但是有名管道文件还在。
这篇关于操作系统-进程间的四种通信(共享内存、消息队列、信号、管道)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!