原文:https://blog.csdn.net/wh_sjc/article/details/70283843
常见的进程间通信(IPC)方式:
1. 管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2. 命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
3. 消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4. 信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
5. 共享内存SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号两,配合使用,来实现进程间的同步和通信。
6. 套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
1.管道,通常指无名管道,是 UNIX 系统IPC最古老的形式。
特点:
1它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
2它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。
3它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。
单个进程中的管道几乎没有任何用处。所以,通常调用 pipe 的进程接着调用 fork,这样就创建了父进程与子进程之间的 IPC 通道。
若要数据流从父进程流向子进程,则关闭父进程的读端(fd[0])与子进程的写端(fd[1]);反之,则可以使数据流从子进程流向父进程。
2. FIFO,也称为命名管道,它是一种文件类型。
特点
1FIFO可以在无关的进程之间交换数据,与无名管道不同。
2 FIFO有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中。
FIFO的通信方式类似于在进程中使用文件来传输数据,只不过FIFO类型文件同时具有管道的特性。在数据读出时,FIFO管道中同时清除数据,并且“先进先出”。
上述例子可以扩展成 客户进程—服务器进程 通信的实例,write_fifo的作用类似于客户端,可以打开多个客户端向一个服务器发送请求信息,read_fifo类似于服务器,它适时监控着FIFO的读端,当有数据时,读出并进行处理,但是有一个关键的问题是,每一个客户端必须预先知道服务器提供的FIFO接口,下图显示了这种安排
3. 消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。
消息队列独立于发送与接收进程。进程终止时,消息队列及其内容并不会被删除。
消息队列(Message Queue),是分布式系统中重要的组件,其通用的使用场景可以简单地描述为:当不需要立即获得结果,但是并发量又需要进行控制的时候,差不多就是需要使用消息队列的时候。
消息队列主要解决了应用耦合、异步处理、流量削锋等问题。
4. 信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。
信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。最简单的信号量是只能取 0 和 1 的变量,这也是信号量最常见的一种形式,叫做二值信号量(Binary Semaphore)。而可以取多个正整数的信号量被称为通用信号量。
特点
1信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
2信号量基于操作系统的 PV操作,程序对信号量的操作都是原子操作。
3每次对信号量的 PV 操作不仅限于对信号量值加1 或减 1,而且可以加减任意正整数。
4 支持信号量组。
5.共享内存:指两个或多个进程共享一个给定的存储区。
特点
1共享内存是最快的一种 IPC,因为进程是直接对内存进行存取。
2 因为多个进程可以同时操作,所以需要进行同步。
3 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问。
五种通讯方式总结
1.管道:速度慢,容量有限,只有父子进程能通讯
2.FIFO:任何进程间都能通讯,但速度慢
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
4.信号量:不能传递复杂消息,只能用来同步
5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存