操作系统之进程间通信篇

本文主要阐述Linux系统中的进程如何进行通信,因为每个进程的用户地址空间都是独立的,一般不能互相访问,但内核空间是每个进程都共享的,所以Linux中的进程通信必须通过内核。在Linux内核进程间通信主要有以下6种方式:

一、管道

概念:把前一个命令的结果当成后一个命令的输入。

管道实质上是内核管理的一个缓冲区,进程写入的数据都存在内核中,另一个进程读取数据时自然也是从内存中读取,同时通信数据遵循先进先出原则,管道的生命周期随进程的创建而建立,随进程的结束而销毁。管道这种通信方式效率低,不适合进程间频繁的交换数据。


 

分类:

  匿名管道:它存在于内存,不存在于文件系统中且没有名字标识,Linux命令中的 就是匿名管道,匿名管道通信的数据是无格式的流且大小受限,通信方式是单向的,匿名管道只能用于存在父子关系的进程间通信。

  命名管道:命名管道实现了毫无关系的进程间通信。

二、消息队列

  消息队列解决了管道的进程间频繁的交换数据效率低的问题,A进程向B进程发送消息,A进程把数据放在对应的消息队列就可以返回了,B进程需要的时候再去读取数据就可以了。消息队列的实质是保存在内核中的消息链表,在发送数据时,会分成一个一个独立的消息体,消息的发送方和接受方都要约定好消息体的数据类型,所以每个消息体都是固定大小的存储块,不像管道是无格式的字节流数据,进程从消息队列中读取了消息体,内核就会把这个信息删除。在通信过程中,存在用户态与内核态之间的数据拷贝开销。


 

缺点:

  1.通信不及时。

  2.不适合较大数据传输。

三、共享内存

  消息队列的读取和写入的过程中,都会有用户态与内核态之间的数据拷贝过程,共享内存则解决了这个问题。在Linux操作系统中,对内存的管理采用的虚拟内存技术,如果对内存管理不熟悉的同学,请看操作系统之内存管理篇。在这里我们只需知道每个进程都有自己独立的虚拟空间,不同进程的虚拟空间映射到不同的物理内存中,即使进程的虚拟地址是一样的,其实访问的是不同的物理地址,对于数据的增删查改互不影响。共享内存的机制就是拿出一块虚拟空间出来,映射到相同的物理内存中。这样进程写入的东西,另一个进程马上就能看见,不需要数据的拷贝,提高了进程间的通信速度。


 

缺点:

  多个进程同时修改同一个共享内存,很有可能会引起冲突。

四、信号量

  信号量主要用于实现进程间的互斥与同步,这里的互斥与同步与线程相同,主要是P、V操作,不懂的同学可以参考操作系统之多线程资源竞争篇,而不是用于缓存进程间通信的数据。信号量防止多进程共享资源,导致数据的混乱。

五、信号

  信号与信号量两者用途完全不一样,上述4种通信方式都是在常规状态下的工作模式,当对于异常情况下的工作模式,就需要用信号的方式来通知进程。信号是进程间通信机制中唯一的异步通信机制,信号事件来源主要有硬件来源(如键盘Ctrl+C)和软件来源(如kill命令)。

 


 

     一旦有信号产生,进程有3种响应信号:

    1.执行默认操作,Linux对每种信号都规定了默认操作。

    2.捕捉信号,可以为信号定义一个信号处理函数,当信号发生时,就执行相应的信号处理函数。

    3.忽略信号,当我们不希望处理某些信号的时候,就忽略信号。

    但是有两个信号是应用进程无法捕捉和忽略的,即SIGINT(kill命令)SEGSTOP,它们用于在任何时候中断或结束某一进程。

六、Socket

    Socket不但可以用于不同主机的进程间通信,还可以用于本地主机进程间通信。

  类型:

    1.基于TCP协议的通信方式。

    2.基于UDP协议的通信方式。

    3.本地进程间通信方式。

 

posted @ 2020-10-13 20:23  zzzgzx  阅读(240)  评论(0编辑  收藏  举报