详解进程之间的通信方式
被面试官问过很多次,下面总结一下几种通信方式,以及如何用代码进行实现
共享内存
-
共享内存原理每个进程都有自己的进程控制块
PCB
和地址空间Addr space
,并且都有一个与之对应的页表,负责将进程之间的虚拟地址与物理地址进行映射,通过内存管理单元进行管理,两个不同的进程的虚拟地址通过页表映射到物理区域的同一区域,它们所指向的内存称为共享内存
-
优缺点
- 优点 速度很快-直接在内存上进行修改,大致过程,PROA->内存->PROB
- 缺点 没有同步机制,需要通过其他手段来进行实现通信同步
-
实现代码
```//shmget 创建共享内存 //return -1 创建共享内存失败 int shmget(key_t key,size_t size,int shmflg); // @ 唯一标识key 根据路与id组成的整数ipc键 key_t ftok(const char *pathname, int proj_id); //shmat 挂在共享内存 void shmat(int shmat,const void* shmataddr,int shmflg); //shmdt 去关联共享内存(当这个进程不需要共享内存了,则将该进程共享内存去关联)) void shmdt(const void *shmataddr); //shmctl 销毁共享内存 int shmctl(int shmid, int cmd, struct shmid_ds *buf);
```
管道通信
-
有名管道
- 无亲缘关系之间的通信方式
- 创建命名管道,设置权限
C++ int mkfifo(const char *pathname, mode_t mode);
- 创建命名管道,设置权限
- 无名管道
- 父子关系之间的通信方式
- 创建一个匿名管道,fd文件描述符数组,其中fd[0]表示读,fd[1]表示写,
返回值:成功返回0,失败返回错误代码
C++ int pipe(int f[2]);
- 创建一个匿名管道,fd文件描述符数组,其中fd[0]表示读,fd[1]表示写,
消息队列
消息队列提供了一个从一个进程向另一个进程发送数据块的方法,每个数据块都可以被认为是有一个类型,接受者接受的数据块可以有不同的类型。
- 主要函数
```//创建和访问一个消息队列 int msgget(key_t key,int msgflag); //消息队列的控制函数 int msgctl(int msqid,int cmd,struct msqid_ds *buf); //把一条消息添加到消息队列中 int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg); //从一个消息队列中接收消息 size_t msgrcv(int msqid,void *msgp,size_t msgsz,long msgtyp,int msgflg);
```
* 优缺点
* 消息队列可以双向通信
* 克服管道只能横在无格式字节流的缺点
套接字
经常写的demo
- 客户端 创建socket->绑定端口号bind->connect->recv/send/wirte/read->close
- 服务端 创建socket->绑定端口号bind->listen->accept->recv/send/write/read->close