Hey,Guys! 给我发条消息吧?
我们知道,无论是在进程互斥还是进程同步中,所有的进程都交换了消息——一个简单的唤醒信号。
虽然只是一个简单的消息,但我们依旧可以将其划分到进程通信中,作为一种低级通信看待(蚊子再小也是肉嘛!)。
有低级通信,那自然也就有高级通信,不过一般而言,我们所说的进程通信都是指高级通信,毕竟互斥和同步都有自己专属的称呼。
进程通信
进程间的互斥,同步以及信息交换统称为进程通信。
进程通信的模式
- 共享内存模式
- 相互通信的进程之间有公共内存,这个公共内存是操作系统分配和管理的,而其使用和基于此的信息传递则是相互通信的进程自己完成的。
- 由于是基于公共内存,故而对其访问需要提供必要的同步机制(等价于共享变量)。
小的时候做过一个传声器,两个纸杯加上一根绳子就可以制作了,但问题就是两个纸杯共用一根绳子,我和朋友只能是一个说,一个听,要不然就听不到对方再说什么了。
- 消息传递模式
在此种模式下的信息传递是不需要公共内存的。操作系统提供提供发送命令(send)和接收命令(receive)这两个系统调用命令来进行消息传递(通信)。
发生消息传递时,只需通信的进程调用这两个命令即可。由于这两个命令是由操作系统提供的,所以命令内部的实现对于用户是透明的。
就像我们打电话,只需要会打电话,会接电话就好了,除了研究这个技术的人,谁会关心怎么实现的这个技术呢?
基于消息传递的实现
直接方式
在这种方式下,进程会直接指定消息源或者接受方,类似于函数的映射,有一对一和多对一的类型。
-
一对一,即对称形式
对称形式 -
多对一,即非对称形式
非对称形式
高中学数学,最痛苦的就是函数的映射关系,开始的时候一看,哎呀,挺简单的,理解了,然后老师上课提问映射的关系......
咦?映射,什么玩意儿?!
浑浑噩噩一个学期之后,什么1-1映射,慢射之类的,还是挺模糊的,不懂,于是就听同桌说,画个函数图像啦,balabala一堆之后,终于懂了。
于是整个高中三年,遇到映射就画个图像......
消息传送的途经
-
带缓冲的途经
高级语言进行文件读写的时候似乎都有带缓冲和不带缓冲的读写?带缓冲流程序开销小,这是由于不需要频繁的进入磁盘读取文件,进程的消息传递也是这样的。
带缓冲的send和receive的具体实现
send和receive命令都是操作系统提供的,使用的时候是要进入操作系统的,而这两者进入操作系统是靠进程产生的自愿性中断实现的。而且有个缓冲区,只需中断一次,读取完消息,回到用户态就可以继续向下执行其他的程序,不用不断的中断读取,直到读取完毕。
-
不带缓冲
不带缓冲的send和receive的具体实现
这看其来可比带缓冲的简单太多了,而且没有了缓冲区,也就节省了空间,但是由于要等待接收进程完成消息接收后才能让发送进程继续推进,这样看来并发性着实太弱了。
间接方式
间接方式和直接方式相对应,是存在媒介进行信息的交换——通信,不需要指明进程具体是哪一个,只需要指明相互通信的进程使用的中间媒介。
这个中间媒介在操作系统中被描述为信箱,所以间接方式也成为信箱方式,在实现这种方式时,信箱既可以属于操作系统空间,也可以是属于用户进程空间,但关于信箱操作的命令则是操作系统提供的(系统调用命令),属于操作系统,来看看关于信箱的定义:
typedef struct mailbox
{
int in, out; //读写内容的位置,初始为0
int k; //消息的个数
semaphore s1, s2; //协调发送和接收的信号量初始为k和0
semaphore mutex; //用于各进程进入信箱的互斥
message letter[k]; //信箱,保存k个消息
}MailBox;
对于信箱的操作定义:
send_MB(MailBox A, message M)
{
P(A.s1);
P(A.mutex);
A.letter[A.in] = M;
A.in = (A.in + 1) % A.k;
V(A.mutex);
V(A.s2);
}
receive_MB(MailBox A, message N)
{
P(A.s2);
P(A.mutex);
N = A.letter[A.out];
A.out = (A.out + 1) % A.k;
V(A.mutex);
V(A.s1);
}
send_MB和receive_MB只是关于信箱的四个命令之一,因为还要创建和删除嘛!
信箱命令的使用权限
话说,朋友之间吵架冷战算是很正常的事情吧?
我上高中那会儿和同桌不知道因为啥原因吵了一架,然后就开始冷战,到后来一次班上六人一组讨论问题(我们开玩笑说这是圆桌会议),关于一个问题又出现分歧,然后我就伸手随便拉住某个人说:“她是不是傻!alabala.....”,我同桌又拽着他:“你告诉他,这么简单的逻辑问题都出错,明显是他傻!”......
想想那兄弟可能也挺无奈的,你说两人都能听到对方说话,还非要找第三人来当传声筒......
小结
在进程通信的模式选择上,没有完美,只有适合于不适合,即便我们说无缓冲的通信并发性差,开销还大,但是耐不住人家实现简单啊,在一些简单的问题实现上和带缓冲的通信差距并不大,那为何要选择带缓冲的通信方式呢?杀鸡焉用牛刀?
这条经验,不仅仅适用于进程通信上,几乎什么事情,这条经验都是实用的。
Hey! Guys! 我发了条消息给你,收到了吗?
网友评论