前言
本文介绍了另一种进程间通信——system V,主要介绍了共享内存,消息队列、信号量,当然消息队列了信号量并非重点,简单了解即可。
一、共享内存
1.共享内存的基本原理
共享内存:不同的进程为了进行通信看到的同一个内存块,该内存块被称为共享内存。
进程具有独立性,它的内核数据结构包括对应的代码,数据与页表都是独立的。
OS系统为了让进程间可以实现通信:1.在物理内存上申请一块内存空间 2.将申请好的内存分别与各个进程的页表之间建立映射,然后在各个进程的虚拟地址空间中将虚拟地址与页表建立映射,从而建立起物理地址与虚拟地址的联系。
如果不想继续通信,就取消进程与内存间的映射关系,释放内存。
- 我们将创建好的内存称为共享内存;
- 将进程与共享内存建立映射的操作称为挂接;
- 把取消进程与内存的映射关系这一操作称为关联;
- 把释放内存称为释放共享内存。
共享内存的建立:在物理内存当中申请共享内存空间;将申请到的共享内存嘎姐到地址空间(建立映射关系)。
共享内存的释放:共享内存与地址空间去关联(取消映射关系),释放共享内存空间(将物理内存归还系统)。
对于共享内存的理解:
对比C语言中的malloc可以在物理内存中申请空间,并将开辟好的空间通过页表映射到进程地址空间当中。system V进程间通信,是专门设计的,用于IPC;共享内存是一种通信方式,所有想进行通信的进程都可以使用(OS一定可能会同时存在很多的共享内存)
2.共享内存的创建
shmget
:用来创建共享内存- 参数认识:
shmflg
:通常有两个选项:IPC_CREAT
、IPC_EXCL
。
IPC_CREAT
:共享内存不存在,则创建,如果存在,则获取。IPC_EXCL
:无法单独使用,只能配合IPC_CREAT
使用。IPC_CREAT | IPC_EXCL
:如果不存在就创建,如果存在就报错。
size
:共享内存的大小
key
:共享内存的唯一性标识,保证进程看到同一份共享内存。如何形成key?用ftok
。
ftok
:形成key
ftok
是通过存在的路径名pathname
以及设置的标识符proj_id
来形成一个key
值,通过shmget
创建共享内存时,key
值会被填充到维护共享内存的数据结构当中。
key_t getkey() { key_t = ftok(PATHNAME, PROJ_JD); if(k < 0) { cout<<"error:"<<errno<<":"<<strerror(errno)<<endl; exit(1); } return k; }
为什么要存在key?
OS中一定存在很多的共享内存,而共享内存本质就是在内存中申请一块空间,这个key就是用来唯一标识共享内存的。
OS申请的共享内存,那么它一定会对共享内存进行管理(先描述,再组织),共享内存 = 物理内存块 + 共享内存的相关属性。
如果两个进程为了进行通信使用共享内存,那么一定要让两干进程看到同一个key的共享内存,那么key值存在哪里呢?key作为共享内存的唯一标识,应该存在共享内存的相关属性集合。描述共享内存的数据结构的字段struct shm中存着key。
共享内存数据结构的第一个成员是shm_perm
,shm_perm
是一个ipc_perm
类型的结构体变量,每个共享内存的key值都存储在shm_perm
中。
// ipc_perm结构体如下 struct ipc_perm{ key_t __key; uid_t uid; gid_t gid; uid_t cuid; gid_t cgid; unsigned short mode; unsigned short __seq; };
3.共享内存的控制
shmctl:控制共享内存
参数
shmid控制共享内存的标识符;
cmd控制种类;
buf控制共享内存的数据结构(一般设置为NULL)。
返回值
返回0表示成功,返回-1表示失败。
共享内存的内核数据结构
struct shmid_ds{ struct ipc_perm shm_perm; size_t shm_segsz; time_t shm_atime; time_t shm_dtime; time_t shm_ctime; pid_t shm_cpod; pid_t shm_lpod; shmatt_t shm_nattch; //…
4.共享内存的关联
shmat
:关联共享内存
参数
shmaddr:指定虚拟地址(一般设置为nullptr);
shmflg:读取权限(一般设置为0)。
5.共享内存的去关联
shmdt:去关联
6.查看IPC资源
对于管道,进程退出,文件描述符会自动被释放(文件描述符的生命周期是随进程的),但是对于共享内存来说不是这样的,共享内存的生命周期是随OS的,而不是随进程,这是所有system V进程间的共性。
7.查看共享内存
ipcs -m
8.删除共享内存
ipcsrm -m (shmid)二、实现进程间通信(代码)
文件comm.hpp