进程间通信的概念
每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到。因此,进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信 IPC(InterProcess Communication)。
进程间通信的应用场景
(1)数据传输
一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间。
(2)共享数据
多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到。
(3)通知事件
一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件。
(4)资源共享
多个进程之间共享同样的资源,需要内核提供锁和同步机制。
(5)进程控制
有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变。
1.管道
管道是通过调用 pipe 函数创建的,fd[0] 用于读,fd[1] 用于写。
#include <unistd.h>
int pipe(intfd[2]);
限制:①只支持半双工通信(单向交替传输);②只能在父子进程或者兄弟进程中使用。
2.FIFO
FIFO也称为管道,与上述管道不同的是没有只能在父子进程中使用的限制。
#include<sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode);
FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户进程和服务器进程之间传递数据。
3.消息队列
消息队列是存放在内核中的消息链表,每个消息队列由消息队列标识符表示。
① 消息队列允许一个或多个进程向它写入与读取消息。
② 管道和消息队列的通信数据都是先进先出的原则
③消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4.信号量
信号量是是一个计数器,用于多个进程之间访问共享数据,即进程间同步。
工作机制:信号量的初值(>0),每当有进程申请使用信号量,通过一个P操作来对信号量进行-1操作。当计数器减到0的时候就说明没有资源了,其他进程要想访问就必须等待。当该进程执行完之后,就会执行V操作来对信号量进行+1操作。
5.共享内存
多个进程可以直接读写同一块内存空间(最快的 IPC )。
工作机制:将不同进程的虚拟内存地址映射到相同的物理内存地址,实现共享内存。内核有一块内存区,可以将进程的私有地址空间映射到该内存区,因此进程间可以直接读写这一块内存而不需要进行数据的拷贝。
6.套接字socket
套接字socket是一种通信机制,实现进程间(本地/跨网络)的通信。socket是应用层和传输层之间的桥梁。
socket通信的基本流程如下: