昆明市环保局建设网站,湛江高端网站开发,建设网站空间多少钱,c2c定义文章目录 0. 代码仓库1. 使用流程案例代码#xff1a; 2. API解析2.1 创建或打开一块共享内存区2.2 将当前进程和共享内存关联到一起2.3 将共享内存和当前进程分离2.4 共享内存操作 -#xff08; 删除共享内存 #xff09; 3. 思考问题3. ftok函数4. 共享内存API封装-以本项… 文章目录 0. 代码仓库1. 使用流程案例代码 2. API解析2.1 创建或打开一块共享内存区2.2 将当前进程和共享内存关联到一起2.3 将共享内存和当前进程分离2.4 共享内存操作 - 删除共享内存 3. 思考问题3. ftok函数4. 共享内存API封装-以本项目为例 0. 代码仓库 https://github.com/Chufeng-Jiang/OpenSSL_Secure_Data_Transmission_Platform 1. 使用流程
向内核申请一块内存 - 指定大小如果有两个进程, 需要通信, 可以使用这块共享内存来完成, 先创建出这两个进程 进程A进程B 进程A和进程B分别和共享内存进行关联 拿到共享内存的地址 - 首地址 两个进程可以通过这个首地址对共享内存进行读/写操作如果这个进程不再使用这块共享内存, 需要和共享内存断开关联 进程退出, 对共享内存是没有任何影响的 当不再使用共享内存的时候, 需要将共享内存销毁
案例代码
https://github.com/Chufeng-Jiang/Linux-System-Programming/tree/main/0110%20Shared%20Memory 2. API解析
2.1 创建或打开一块共享内存区
// 创建共享内存
// 共享内存已经存在, 打开共享内存
// 可以创建多块共享内存int shmget(key_t key, size_t size, int shmflg);参数:- key: 通过这个key记录共享内存在内核中的位置, 需要是一个0的整数, 0不行随便指定一个数就可以, 后边会介绍一个函数ftok- size: 创建共享内存的时候, 指定共享内存的大小- 如果是打开一个已经存在的共享内存, size写0就可以- shmflg: 创建共享内存的时候使用, 类似于open函数的flag- IPC_CREAT: 创建共享内存- 创建的时候需要给共享内存一个操作权限- IPC_CREAT | 0664- IPC_CREAT | IPC_EXCL: 检测共享内存是否存在- 如果存在函数返回-1- 不存在, 返回0返回值:成功: 创建/打开成功, 得到一个整形数 - 对应这块共享内存失败: -1// 应用
// 1. 创建共享内存
int shmid shmget(100, 4096, IPC_CREAT | 0664);
int shmid shmget(200, 4096, IPC_CREAT | 0664);
// 2. 打开共享内存
int shmid shmget(100, 0, 0); 2.2 将当前进程和共享内存关联到一起
// 进程和共享内存产生关系
void *shmat(int shmid, const void *shmaddr, int shmflg);参数:- shmid: 通过这个参数访问共享内存, shmget()函数的返回值- shmaddr: 指定共享内存在内核中的位置, 写NULL - 委托内核区指定- shmflg: 关联成功之后对共享内存的操作权限- SHM_RDONLY: 只读- 0: 读写返回值:成功: 共享内存的地址 (起始地址)失败: (void *) -1// 函数调用:
void* ptr shmat(shmid, NULL, 0);
// 写内存
memcpy(ptr, xxxx, len);
// 读内存
printf(%s, (char*)prt);2.3 将共享内存和当前进程分离
// 进程和共享内存分离 - 二者就没有关系了
int shmdt(const void *shmaddr);参数: 共享内存的起始地址, shmat()返回值返回值:- 成功: 0- 失败: -12.4 共享内存操作 - 删除共享内存
// fcntl
// setsockopt
// getsockopt
// 对共享内存进程操作
int shmctl(int shmid, int cmd, struct shmid_ds *buf);参数: - shmid: 通过这个参数访问共享内存, shmget()函数的返回值- cmd: 对共享内存的操作- IPC_STAT: 获取共享内存的状态- IPC_SET: 设置共享内存状态- IPC_RMID: 标记共享内存要被销毁- buf: 为第二个参数服务的cmdIPC_STAT: 获取共享内存具体状态信息cmdIPC_SET: 自定义共享内存状态, 设置到内核的共享内存中cmdIPC_RMID: 这个参数没有用了, 指定为NULL返回值:成功: 0失败: -1// 删除共享内存
shmctl(shmid, IPC_RMID, NULL);3. 思考问题 问题1: 操作系统如何知道一块共享内存被多少进程关联? 共享内存维护了一个结构体struct shmid_ds这个结构体中有一个成员shm_nattchshm_nattch中记录了关联的进程的个数 问题2: 是不是可以对共享内存进行多次删除 - 多次调用shmctl 可以多次操作 因为shmctl函数是标记删除共享内存, 部署直接删除 什么时候被真正删除了?当关联这块共享内存进程个数 0 的时候, 真正被删除了 shm_nattch 0
3. ftok函数
ftok函数是IPC中常用的一个函数,它是由Unix系统提供的一个应用程序编程接口(API)。它的作用是根据一个指定的文件名和一个整数,生成一个不重复的键值(key)。 key_t ftok(const char *pathname, int proj_id); 首先根据一个任意存在的pathname绝对路径提取其所属文件系统的特有信息包括设备号(stat.st_dev)和inode号(stat.st_ino)其获取方法参见上述程序中的sata结构然后再结合ftok()函数的proj_id参数按照如下规则计算key
key1 stat.st_ino 0xffff; // 保留低16位
key2 stat.st_dev 0xff; // 保留低8位
key2 16; // 左移16位
key3 proj_id 0xff; // 保留低8位
key3 24; // 左移24位
key key1|key2|key3; // 三者进行或运算本例中pathname’/tmp‘ftok()函数提取的设备号为0x804inode号为0x280001proj_id为0x01根据以上运算过程key10x01key20x40000key30x1000000三者求或得到key0x1040001与程序输出的结果一致。
4. 共享内存API封装-以本项目为例
//shmget
int shmget(key_t key, size_t size, int shmflg);
class BaseShm
{
public:BaseShm(int key); // 根据key打开共享内存BaseShm(string path); // 根据string path- int key 打开共享内存BaseShm(int key, int size); // 根据key创建共享内存BaseShm(string path, int size); // 根据string path- int key 创建共享内存void* mapshm(){m_ptr shmat(shmid);return m_ptr;}int unmapshm(){shmdt(m_ptr);}int delshm(){shmctl(shmid);}private:int m_shmid; // shmget返回值void* m_ptr;
}