System V IPC对象 - 共享内存
System V IPC对象:
相对unix中linux引入的。
IPC对象包含:共享内存、消息队列和信号灯集。
每个IPC对象有唯一的ID,创建的时候返回给调用者。
IPC对象创建后一直存在,直到被显式地删除,和管道不同管道在所有的读端和写端都关闭的时候就会自动删除。
每个IPC对象有一个关联的KEY,IPC对象的属性,不同的进程可以通过KEY值来找到和打开对象。
只有创建该IPC对象的进程才可见IPC对象的ID,其它进程不可见。每个IPC对象在创建的时候需要指定一个KEY值,把KEY值和该IPC对象关联起来,其他进程就可以通过这个KEY来找到这个IPC对象,如果KEY值被设置成0代表该IPC对象是进程私有的。为避免用户自己指定的KEY值会重复,系统提供一个专门的函数产生KEY值。
查看系统中创建的IPC对象:
ipcs

删除系统中创建的一个IPC对象:
ipcrm […]
IPC对象创建、使用流程:

生成key值函数:
key值生成原理:用ftok()函数第一个参数“文件在文件系统的i节点值”和第二个参数proj_id的低八位移位生成key值。proj_id必须是非零值,实际常指定一个字符常量。
1 |
|
System V IPC-ftok-示例:
要想不同的进程使用同一个IPC对象,进程在ftok()创建key值时传的参数必须一致。
1 |
|
共享内存
共享内存是进程直接读写内核空间的内存进行进程之间数据交换,而其他IPC对象机制是在内核内存创建一块空间,数据要同步到进程自己的内存空间。
共享内存是一种最为高效的进程间通信方式,进程可以
直接读写内存,而不需要任何数据的拷贝。共享内存在内核空间创建,可被进程映射到用户空间访
问,使用灵活。由于多个进程可同时访问共享内存,因此需要同步和互
斥机制配合使用。
共享内存使用步骤
- 创建/打开共享内存
- 映射共享内存,即把指定的共享内存映射到进程的地址
- 空间用于访问
- 读写共享内存
- 撤销共享内存映射
- 删除共享内存对象
共享内存创建:
1 |
|
共享内存创建 - shmget - 示例1
要求:创建一个私有的共享内存,大小为512字节,权限
为0666
1 | int shmid; |
共享内存创建 - shmget - 示例2
要求:创建/打开一个和key关联的共享内存,大小为1024
字节,权限为0666
1 | key_t key; |
所有进程使用共享内存之前都要运行上面一模一样的代码,第一个运行这段代码的进程是正真创建共享内存,后面运行的代码是通过key找到共享内存shmid并不是创建一个新的,因为第一个进程已经把key和这个共享内存绑定了。shmget函数发现第一个参数key已经绑定有一个共享内存了就会直接返回这个共享内存的id。
小结:
共享内存效率最高没有内存拷贝,进程直接读写内核里面的内存。
由于共享内存可以被多个进程访问,所以需要用同步和互斥机制配合对共享内存访问。
1.共享内存映射 - shmat
1 |
|
- 通过指针访问共享内存,指针类型取决于共享内存中存 放的数据类。
例如:在共享内存中存放键盘输入的字符串
1 | char *addr; |
2.共享内存撤销映射 - shmdt
1 |
|
3.共享内存控制 - shmctl
1 |
|
4.共享内存使用的注意事项
每块共享内存大小有限制
1 | ipcs -1 |
共享内存删除的时间点
shmct(shmid, IPC-RMID, NULL) 添加删除标记,正真删除内存要满足共享内存被标记删除并且所以的进程都取消了对这块空闲内存的地址映射。struct shmid_ds共享内存结构体中nattach变量用于记录共享内存被多少个进程地址映射了。消息队列和信号灯和共享内存不一样调用删除函数就直接删除。
查看ips对象可占用内存最大值:

小结:
1.shmat:共享内存映射到进程内地址,会返回一个代表这块共享内存的首地址地址
2.shmdt:取消共享内存地址映射,传入共享内存的首地址
3.shmctl:可以通过id获取一块共享内存的属性、设置共享内存属性、删除共享内存
4.共享存储的访问就是通过指针,要读写什么类型的数据就把指针转换成该类型的数据