目录
一、IPC简介
进程间通信(interprocess communication,简称IPC)指两个进程之间的通信。
系统中的每一个进程都有各自的地址空间,并且相互独立、隔离,每个进程都处于自己的地址空间中。所以同一个进程的不同模块(譬如不同的函数)之间进行通信都是很简单的,譬如使用全局变量等。
但是,两个不同的进程之间要进行通信通常是比较难的,因为这两个进程处于不同的地址空间中。如果要交换数据,必须要通过内核,在内核中开辟一块缓冲区,进程A把数据从用户空间拷贝到内核缓冲区,进程B再把数据从内核缓冲区拷贝走------即IPC。
通常情况下,大部分的程序是不要考虑进程间通信的,因为大部分程序都是单进程程序(可以有多个线程),对于一些复杂、大型的应用程序,则会根据实际需要将其设计成多进程程序,譬如GUI、服务区应用程序等。
二、管道和FIFO
管道包括三种:
普通管道pipe:通常有两种限制,一是单工,数据只能单向传输;二是只能在父子或者兄弟进程间使用;
流管道s_pipe:去除了普通管道的第一种限制,为半双工,可以双向传输;只能在父子或兄弟进程间使用;
有名管道name_pipe(FIFO):去除了普通管道的第二种限制,并且允许在不相关(不是父子或兄弟关系)的进程间进行通讯。
普通管道可用于具有亲缘关系的进程间通信,并且数据只能单向传输,如果要实现双向传输,则必须要使用两个管道;
流管道去除了普通管道的第一种限制,可以半双工的方式实现双向传输,但也只能在具有亲缘关系的进程间通信;
有名管道(FIFO)则同时突破了普通管道的两种限制,即可实现双向传输、又能在非亲缘关系的进程间通信。
三、信号
信号是事件发生时对进程的通知机制,也可以把它称为软件中断。信号与硬件中断的相似之处在于能够打断程序当前执行的正常流程,其实是在软件层次上对中断机制的一种模拟。大多数情况下,是无法预测信号达到的准确时间,所以,信号提供了一种处理异步事件的方法。
信号是异步事件的经典实例,产生信号的事件对进程而言是随机出现的,进程无法预测该事件产生的准确时间,进程不能够通过简单地测试一个变量或使用系统调用来判断是否产生了一个信号,这就如同硬件中断事件,程序是无法得知中断事件产生的具体时间,只有当产生中断事件时,才会告知程序、然后打断当前程序的正常执行流程、跳转去执行中断服务函数 ------即异步处理方式。
每个进程收到的所有信号,都是由内核负责发送的,内核处理。
四、消息队列
消息队列是消息链表,存放在内核中并由消息队列标识符标识。
一个消息队列由一个标识符来标识,进程可以从中读写数据。消息队列不属于某个进程,创建之后,即使该进程结束,消息队列依然存在,其他进程依然可以读写数据。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺陷。消息队列包括POSIX消息队列和System V消息队列。
系统允许不同进程将格式化的数据流以消息队列形式发送给任意进程,有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。
五、信号量
信号量相当于一个计数器 ,与其它进程间通信方式不大相同,它主要用于控制多个进程间或一个进程内的多个线程间对共享资源的访问,相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时,进程也可以修改该标志,除了用于共享资源的访问控制外,还可用于进程同步。
它常作为一种锁机制,防止某进程在访问资源时其它进程也访问该资源,因此,主要作为进程间以及同一个进程内不同线程之间的同步手段。Linux提供了一组信号量接口来对信号量进行操作,它们声明在头文件sys/sem.h中。
信号量的PV操作:
P操作:我们将申请信号量称为P操作,申请信号量的本质就是申请获得临界资源中某块资源的使用权限,当申请成功时临界资源中资源的数目应该减一,因此P操作的本质就是让计数器减一。
V操作:我们将释放信号量称为V操作,释放信号量的本质就是归还临界资源中某块资源的使用权限,当释放成功时临界资源中资源的数目就应该加一,因此V操作的本质就是让计数器加一。
六、共享内存
共享内存即是映射一段能被其它进程所访问的内存,这段共享内存由一个进程创建,但其它的多个进程都可以访问,使得多个进程可以访问同一块内存空间。共享内存是最快的IPC方式,它是针对其它进程间通信方式运行效率低而专门设计的,它往往与其它通信机制,譬如结合信号量来使用,以实现进程间的同步和通信。
七、嵌套字(Socket)
Socket是一种IPC方法,是基于网络的IPC方法,允许位于同一主机(计算机)或使用网络连接起来的不同主机上的应用程序之间交换数据 ------即网络通信。
在一个典型的客户端/服务器场景中,应用程序使用socket进行通信的方式如下:
①各个应用程序创建一个socket。socket是一个允许通信的"设备",两个应用程序都需要用到它。
②服务器将自己的socket绑定到一个众所周知的地址(名称)上使得客户端能够定位到它的位置。