进程间通信可以通过传送打开文件(fork,exec与文件系统)来实现,不同的进程通过一个或多个文件来传递信息,事实上,在很多应用系统里,都使用了这种方法。但一般说来,进程间通信不包括这种似乎比较低级的通信方法。
特点:
无名管道是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
因为没有名字,因此无名管道只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
无名管道只存在于内存中,其实质是一个内核缓冲区。进程以先进先出的方式从缓冲区存取数据:管道一端的进程顺序地将进程数据写入缓冲区,另一端的进程则顺序地读取数据。
无名管道由pipe()函数创建:
#include
int pipe(int filedis[2]);
参数filedis返回两个文件描述符:filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输入。
命名管道和无名管道的主要区别在于,命名管道有一个文件名字,这个文件名对应于一个磁盘索引节点,有了这个文件名,任何进程有相应的权限都可以对它进行访问。
Linux中通过系统调用mknod()或makefifo()来创建一个命名管道。
mkfifo myfifo
mknod myfifo p
消息队列与管道通信相比,其优势在于接收的时候不需要按照队列次序,而是可以根据自定义条件接收特定类型的消息。
共享内存机制其允许两个或多个进程共享一个给定的存储区,这一段存储区可以被两个或两个以上的进程映射至自身的地址空间中,一个进程写入共享内存的信息,可以被其他使用这个共享内存的进程,通过一个简单的内存读取错做读出,从而实现了进程间的通信。
采用共享内存进行通信的一个主要好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝,对于像管道和消息队里等通信方式,则需要再内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次:一次从输入文件到共享内存区,另一次从共享内存到输出文件。
信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
特点
P操作:信号量的值减1,若信号量的值减1后小于0,则该进程被阻塞后放入等待该信号量的等待队列中。
V操作:信号量的值加1,若信号量的值加1后的结果小于或等于0,则从该信号的等待队列中释放一个等待进程。
内核进程利用信号来通知用户进程发生了哪些系统事件,用户进程对信号的响应方式如下:
Unix域套接字用于同一台pc上运行的进程之间通信,它仅仅复制数据,不执行协议处理(比如增加删除网络报头,计算校验和,产生顺序号,发送确认报文),因此Unix域套接字往往比通信两端位于同一主机的TCP套接字要快。
套接字Socket
套接口(socket)编程是实现不同计算机中进程间通信的主要方式之一。我们熟知的WWW服务、FTP服务、TELNET服务等都是基于套接口编程来实现的。除了在异地的计算机进程间以外,套接口同样适用于本地同一台计算机内部的进程间通信。
共享内存是最高效的进程间通信的方式,因为把同一块物理内存的地址空间映射到不同进程的地址空间当中,那么不同的进程之间通信,通过直接修改地址空间当中的内存即可,该机制的实现只需要两次拷贝即可实现,即数据从用户空间到内存,数据再从内存到用户空间。
其它的进程通信机制需要四次拷贝操作。假设现在A和B间需要通信,首先从进程A的缓冲区中将数据拷贝到内核中,其次内核将数据拷贝到内存中,之后数据又从内存被拷贝到内核,最后内核将数据拷贝到进程B的缓冲区中。因此使用共享内存通信比较高效。