|
进程间为什么需要数据通信?
- 数据传输:一个进程需要将它的数据传送给另外一个进程。
- 资源共享:多个进程之间共享相同的资源。
- 通知事件:一个进程需要向另外一组进程发送消息,通知它们发生了某种事件。
- 进程控制:有些进程需要完全控制另一个进程的执行,该控制进程希望能够拦截另外一个进程的所有操作,并且能够及时知道它的状态改变。
主要有管道、消息队列、共享内存、信号量、信号、Socket等六种方式。
管道
管道的本质是内核中的一个缓存,当内存创建一个管道后,Linux会返回两个文件描述符号,一个是写入端的描述符,一个是输出端的描述符,可以通过这两个描述符往管道里写入或者读取数据。如果想要实现两个进程通过管道来通信,则需要让创建管道的进程fork子进程,这样子进程就拥有了父进程的文件描述符,这样子进程之间可以对同一管道的操作。管道这种进程通信方式虽然使用简单,但是效率比较低,不适合进程间频繁地交换数据,并且管道只能传输无格式的字节流。
消息队列
消息队列的本质就是存放在内存中的消息链表,而消息本质上是用户自定义的数据结构。如果进程在消息队列种读取了某个消息,这个消息就会被从消息队列种删除。
- 消息队列允许一个或者多个进程向他写入或者读取数据。
- 消息队列可以不遵循FIFO,进行消息随机查询。
- 消息队列的生命周期与内核相同。
- 消息队列对于交换较少数量的数据很有用,因为无需避免冲突。因为用户进程往消息队列种读写数据,需要进行系统调用。如果数据量大会造成频繁的系统调用,因此需要更多的时间以便于内核介入。
共享内存
共享内存就是允许不相干的进程将同一段物理内存连接到它们各自的地址空间中,使得这些内存可以访问同一个物理空间,这个物理内存就成为共享内存。
- 两个不同进程的逻辑地址通过页表映射到物理空间的同一区域,它们所共同指向的这块区域就是共享内存。
- 消息队列无需避免冲突,而共享内存机制可能会发生冲突。
信号量
在多道批处理系统中,多个进程是可以并发执行的,但由于系统的资源有限,进程的执行不是一贯到底的, 而是走走停停,以不可预知的速度向前推进(异步性)。但有时候我们又希望多个进程能密切合作,按照某个特定的顺序依次执行,以实现一个共同的任务。
为了解决上述这两个问题,保证共享内存在任何时刻只有一个进程在访问(互斥),并且使得进程们能够按照某个特定顺序访问共享内存(同步),我们就可以使用进程的同步与互斥机制,常见的比如信号量与 PV 操作。进程的同步与互斥其实是一种对进程通信的保护机制,并不是用来传输进程之间真正通信的内容的,但是由于它们会传输信号量,所以也被纳入进程通信的范畴,称为低级通信。
<ul>信号量:信号量其实就是一个变量 ,我们可以用一个信号量来表示系统中某种资源的数量。例如系统连接的打印机资源的数量,可以设置一个初值为1的信号量。
原语:操作系统提供的一对原语来对信号量进行操作。<ul>
P操作:信号量--,表示申请占用一个资源。如果申请结果小于0,则无资源可用,P操作的进程被阻塞。
V操作:信号量++,表示释放一个资源。如果信号量+1 |
|