提示:以下是本篇文章正文内容,下面案例可供参考
一、相关概念
共享内存示意图:
共享内存区是最快的进程间通信(IPC)形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到
内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据
二、相关函数
0.ftok
用于生成一个 System V IPC键值的函数。这个键值通常用于创建共享内存段、消息队列和信号量
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
参数:
- pathname:路径名
- proj_id:项目标识符(project identifier)
不同的路径名结合相同的项目标识符会生成相同的键值。所以,如果多个进程希望访问同一个共享内存段、消息队列或信号量,它们需要使用相同的路径名和项目标识符作为参数调用 ftok 函数。
1.shmget
这个函数用于创建共享内存
#include <sys/types.h>
#include <sys/ipc.h>
int shmget(key_t key, size_t size, int shmflg);
-
key:用于创建共享内存段的键值,需要用函数ftok获得
-
size:共享内存大小,单位是字节
-
shmflg:用法和创建文件时使用的mode模式标志是一样的,一般常见的选项是IPC_CREAT 和 IPC_EXCL
单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回
IPC_EXCL不能单独使用,一般都要配合IPC_CREAT
IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回
还可以举出一些其他的例子:
如果看到shmget(k,size,IPC_CREAT | IPC_EXCL | 0666),
则表示“如果不存在指定键值的共享内存,则创建一个新的共享内存,并赋予读写权限给用户、用户组和其他用户。如果已经存在相同键值的共享内存,返回错误”
2.shmat
将已创建好的共享内存段连接到进程地址空间
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);
- shmid: 共享内存的标识码,需要从shmget来获得
- shmaddr:指定连接的地址,这个参数提供给使用者一个选择,来控制创建出的虚拟内存挂接到虚拟内存指定的区域
但由于我们啥也不知道,所以使用的时候填nullptr,让操作系统帮我们链接过去就好
3.shmdt
将共享内存段与当前进程脱离
#include <sys/types.h>
int shmdt(const void *shmaddr);
- shmaddr: 由shmat所返回的指针
- 函数成功时返回0;失败时返回-1
- 将共享内存段与当前进程脱离不等于删除共享内存段
4.shmctl
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
- shmid:由shmget返回的共享内存标识码
- cmd:将要采取的动作(有三个可取值)
- buf:指向一个保存着共享内存的模式状态和访问权限的数据结构,在只需要删除删除的时候,buf这个参数填nullptr就可以
- cmd选项:
5.总结
为了让两个进程之间实现通信,需要做到以下几点:
- 使用ftok函数生成键值,由于我们希望多个进程访问同一块内存,所以两段代码里面需要使用相同的路径名和项目标识符作为参数调用 ftok 函数
- 使用shmget以后用shmat连接,用完了以后用shmdt解除连接,最后用shmctl删除用完的共享内存
三、示例代码
假设我们需要使用共享内存来让两个进程实现通信:
进程A 向共享内存当中写 “i am process A”
进程B 从共享内存当中读出内容
左边的代码是进程A的代码A.cc,另一段就是进程B的代码B.cc
运行的时候需要先运行进程A,然后才是进程B