Openssl数据安全传输平台007:共享内存及代码的实现 ——待完善项目具体代码和逻辑

文章目录

  • 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. 使用流程

  1. 向内核申请一块内存 -> 指定大小
  2. 如果有两个进程, 需要通信, 可以使用这块共享内存来完成, 先创建出这两个进程
    • 进程A
    • 进程B
  3. 进程A和进程B分别和共享内存进行关联
    • 拿到共享内存的地址 -> 首地址
  4. 两个进程可以通过这个首地址对共享内存进行读/写操作
  5. 如果这个进程不再使用这块共享内存, 需要和共享内存断开关联
    • 进程退出, 对共享内存是没有任何影响的
  6. 当不再使用共享内存的时候, 需要将共享内存销毁

案例代码:

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- 失败: -1

2.4 共享内存操作 -( 删除共享内存 )

// fcntl
// setsockopt
// getsockopt
// 对共享内存进程操作
int shmctl(int shmid, int cmd, struct shmid_ds *buf);参数: - shmid: 通过这个参数访问共享内存, shmget()函数的返回值- cmd: 对共享内存的操作- IPC_STAT: 获取共享内存的状态- IPC_SET: 设置共享内存状态- IPC_RMID: 标记共享内存要被销毁- buf: 为第二个参数服务的cmd==IPC_STAT: 获取共享内存具体状态信息cmd==IPC_SET: 自定义共享内存状态, 设置到内核的共享内存中cmd==IPC_RMID: 这个参数没有用了, 指定为NULL返回值:成功: 0失败: -1// 删除共享内存
shmctl(shmid, IPC_RMID, NULL);

3. 思考问题

  • 问题1: 操作系统如何知道一块共享内存被多少进程关联?

    • 共享内存维护了一个结构体struct shmid_ds这个结构体中有一个成员shm_nattch
    • shm_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()函数提取的设备号为0x804,inode号为0x280001,proj_id为0x01,根据以上运算过程,key1=0x01,key2=0x40000,key3=0x1000000,三者求或得到key=0x1040001,与程序输出的结果一致。

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;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/145081.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins+Ant+Jmeter接口自动化集成测试

一、Jenkins安装配置 1、安装配置JDK1.6环境变量&#xff1b; 2、下载jenkins.war&#xff0c;放入C:\jenkins目录下&#xff0c;目录位置随意&#xff1b; Jenkins启动方法&#xff1a; cmd进入Jenkins目录下&#xff0c;执行java -jar jenkins.war 浏览器输入&#xff1a;l…

KingBase库模式表空间和客户端认证(kylin)

库、模式、表空间 数据库 数据库基集簇与数据库实例 KES集簇是由单个KES实例管理的数据库的集合KES集簇中的库使用相同的全局配置文件和监听端口、共享相关的进程和内存结构同一数据库集簇中的进程、相关的内存结构统称为实例 数据库 数据库是一个长期存储在计算机内的、有…

【网络】HTTPS讲解(侧重于加密、秘钥、证书的讲解)

HTTPS讲解 前言正式开始安全HTTP和HTTPS的关系什么是加密和解密为什么要加密运营商劫持中间人 常⻅的加密⽅式对称加密⾮对称加密 数据摘要数字签名HTTPS 的⼯作过程⽅案 1 - 只使⽤对称加密&#xff08;不可靠&#xff09;⽅案 2 - 只使⽤⾮对称加密&#xff08;不可靠&#x…

【React】高频面试题

1. 简述下 React 的事件代理机制&#xff1f; React使用了一种称为“事件代理”&#xff08;Event Delegation&#xff09;的机制来处理事件。事件代理是指将事件处理程序绑定到组件的父级元素上&#xff0c;然后在需要处理事件的子元素上触发事件时&#xff0c;事件将被委托给…

ScrapeKit 和 Swift 编写程序

以下是一个使用 ScrapeKit 和 Swift 编写的爬虫程序&#xff0c;用于爬取 图片。同时&#xff0c;我们使用了proxy 这段代码来获取代理。 import ScrapeKit ​ class PeopleImageCrawler: NSObject, ScrapeKit.Crawler {let url: URLlet proxyUrl: URL ​init(url: URL, proxy…

掌握Java中的volatile关键字

高速缓存 什么是高速缓存 高速缓存&#xff08;Cache&#xff09;是一种用于存储计算机数据的临时存储设备&#xff0c;用于加速数据访问速度&#xff0c;减少对主存储器&#xff08;RAM&#xff09;或磁盘的频繁访问。高速缓存通过将最常用的数据存储在更接近CPU的位置&…

数字孪生与智慧城市:重塑未来城市生活的奇迹

今天&#xff0c;我们将探讨数字孪生和智慧城市两个颠覆性技术&#xff0c;它们正引领着未来城市生活的巨大变革。随着科技的飞速发展&#xff0c;数字孪生和智慧城市成为实现可持续发展和提升居民生活质量的关键策略。 数字孪生&#xff1a;实现现实与虚拟的完美融合 数字孪生…

Linux进程与线程的内核实现

进程描述符task_struct 进程描述符&#xff08;struct task_struct&#xff09;pid与tgid进程id编号分配规则内存管理mm_struct进程与文件,文件系统 进程,线程创建的本质 clone函数原型线程创建的实现进程创建的实现 总结 进程描述符task_struct 进程描述符&#xff08;st…

centos如何根据端口号查询程序路径

centos如何根据端口号查询程序路径 如果是半路接受的应用&#xff0c;上个人只给你说了程序的端口号&#xff0c;别的都没&#xff0c;那怎么找程序的路径哪&#xff1f;一是给上上个人要&#xff0c;二是自己找&#xff08;我是自己找的&#xff09; 小白教程&#xff0c;一…

【字符函数】

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 &#x1f388;相关博文&#xff1a;字符串函数&#xff08;一&#xff09;、字符串函数&#xff08;二&#xff09; 字符函数 字符函数1.字符分类函数1.1 iscntrl - 判断是否是控制字符1.2 i…

el-input单独校验

el-input单独校验,效果图如下 <el-col :span"24"><el-form-item label"修订次数:" prop"sPublish"><el-input-numberv-model"addForm.sPublish":min"0":controls"false":precision"0"p…

OpenCV+QT实现的数字图像处理算法合集

源码下载地址&#xff1a; 基于OpenCV和QT的图像处理源码 图像预处理 灰度处理 灰度直方图 灰度均衡 梯度锐化 Laplace锐化 边缘检测 Roberts Sobel Laplace Prewitt canny Krisch 噪声 椒盐噪声 高斯噪声 滤波 均值滤波 中值滤波 双边滤波 形态学滤波 高斯滤波 图像变…