常见的通信方式:
1. 管道pipe:管道是一种半双工的通信方式,数据只能单向流动,需要双方通信时,需要建立起两个管道;
而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2. 命名管道FIFO:有名管道也是半双工的通信方式,支持可靠的、单向或双向的数据通信。但是它允许无亲缘关系进程间的通信。
遵循先进先出(first in first out),对管道PIPE及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。
3. 信号 ( sinal ):所能携带的信息有限,他只是通知其他进程一个信号,而不能发送具体的数据。用于通知接收进程某个事件已经发生。
4. 消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。
消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
缺点:
A. 与管道一样,每个数据块有一个最大长度的限制。
B. 系统中所有队列所包含的全部数据块的总长度也有一个上限。
Linux系统中有两个宏定义:
MSGMAX, 以字节为单位,定义了一条消息的最大长度。
MSGMNB, 以字节为单位,定义了一个队列的最大长度。
限制:
由于消息缓冲机制中所使用的缓冲区为共用缓冲区,因此使用消息缓冲机制传送数据时,两通信进程必须满足如下条件。
(1)在发送进程把写入消息的缓冲区挂入消息队列时,应禁止其他进程对消息队列的访问,否则,将引起消息队列的混乱。
同理,当接收进程正从消息队列中取消息时,也应禁止其他进程对该队列的访问。
(2)当缓冲区中无消息存在时,接收进程不能接收任何消息;而发送进程是否可以发送消息,则只由发送进程是否能够申请缓冲区决定。
5. 共享内存SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。
这是因为所有进程共享同一块内存,共享内存在各种进程间通信方式中具有最高的效率。访问共享内存区域和访问进程独有的内存区域一样快,
并不需要通过系统调用或者其它需要切入内核的过程来完成。同时它也避免了对数据的各种不必要的复制。
但共享内存最大的问题就是多进程竞争内存的问题,就像类似于我们平时说的线程安全问题。如何解决这个问题?它往往与其他通信机制,如信号量配合使用,来实现进程间的同步和通信。
因为系统内核没有对访问共享内存进行同步,您必须提供自己的同步措施。例如,在数据被写入之前不允许进程从共享内存中读取信息、
不允许两个进程同时向同一个共享内存地址写入数据等。解决这些问题的常用方法是通过使用信号量进行同步。
6. 信号量Semaphore:信号量本质:具有一个等待队列的计数器,用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。
因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
信号量计数器大于0,代表信号量有资源,可以操作;
信号量计数器等于0,代表信号量没有资源,需要等待。
7. 套接字Socket:
上面我们说的管道、消息队列,共享内存、信号量、他们都是多个进程在一台主机之间的通信,那两个相隔几千里的进程能够进行通信吗?这个时候 Socket 这家伙就派上用场了,例如我们平时通过浏览器发起一个 http 请求,然后服务器给你返回对应的数据,这种就是采用 Socket 的通信方式了.