第四章 sysrepo共享内存机制
1、共享内存机制
Sysrepo0.X.X版本使用的进程间通信的机制,在实际的使用过程中,出现了诸如数据不同步、数据处理TimeOut、完成一次Get请求时,但实际处理的请求会较多,导致性能与规格上不去的各类问题。Sysrepo-devel分支开始引入共享机制后,合入到Sysrepo的Master分支,也就是现在的 Sysrepo1.X.X版本。
简单说一说什么是共享内存,共享内存就是允许两个或多个进程共享一定的存储区,说白了,就是两个进程访问同一块内存区域,当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改,所以数据不需要在客户机和服务器端之间复制,数据直接写到内存,不用若干次数据拷贝,是一种最快的IPC。原理图如下所示,需要注意的是,共享内存本向并没有任何的同步与互斥机制,所以必须使用信号量来实现对共享内存的存取的同步。其它有关的共享内存的概念使用,网上有很多,可自行查阅理解。本处这分析与sysrepo相关的共享内存机制的使用。
图1 共享内存原理图
2、数据结构
/*** @brief Generic shared memory information structure.*/
//sysrepo 共享内存数据结构
typedef struct sr_shm_s {int fd; /**< Shared memory file desriptor. */size_t size; /**< Shared memory mapping current size. */char *addr; /**< Shared memory mapping address. */
} sr_shm_t;Sysrepo定义了两个SHM分段,一个是main SHM 和ext SHM
#define SR_MAIN_SHM "/sr_main" /**< Main SHM name. */
#define SR_EXT_SHM "/sr_ext" /**< External SHM name. */
除了定义定义的main和ext分段之外,还有用于subscriptions和running数据文件的单个的SHM分段。
main SHM是以sr_main_shm_t结构开始,结构定义如下:
typedef struct sr_main_shm_s {sr_rwlock_t lock; /**< Process-shared lock for accessing main and ext SHM. It is * required only when accessing attributes that can be changed * (subscriptions, replay support) and do not have their own lock * (conn state), otherwise not needed. */pthread_mutex_t lydmods_lock; /**< Process-shared lock for accessing sysrepo module *data. */uint32_t mod_count; /**< Number of installed modules stored after this structure. */off_t rpc_subs; /**< Array of RPC/action subscriptions. */uint16_t rpc_sub_count; /**< Number of RPC/action subscriptions. */ATOMIC_T new_sr_sid; /**< SID for a new session. */ATOMIC_T new_evpipe_num; /**< Event pipe number for a new subscription. */struct {pthread_mutex_t lock; /**< Process-shared lock for accessing connection state. */off_t conns; /**< Array of existing connections. */uint32_t conn_count; /**< Number of existing connections. */} conn_state; /**< Information about connection state. */
} sr_main_shm_t;
后面是是所有安装的模块,每个安装的模块都会带sr_mod_t结构直接到main SHM的定义结构。
typedef struct sr_mod_s sr_mod_t;
/*** @brief Main SHM module.* (typedef sr_mod_t)*/
struct sr_mod_s {struct sr_mod_lock_s {sr_rwlock_t lock; /**< Process-shared lock for accessing module instance data. */uint8_t write_locked; /**< Whether module data are WRITE locked (lock itself may not be WRITE locked to allow data reading). */uint8_t ds_locked; /**< Whether module data are datastore locked (NETCONF locks). */sr_sid_t sid; /**< Session ID of the locking session (user is always NULL). */time_t ds_ts; /**< Timestamp of the datastore lock. */} data_lock_info[SR_DS_COUNT]; /**< Module data lock information for each datastore. */sr_rwlock_t replay_lock; /**< Process-shared lock for accessing stored notifications for replay. */uint32_t ver; /**< Module data version (non-zero). */off_t name; /**< Module name. */char rev[11]; /**< Module revision. */uint8_t flags; /**< Module flags. */off_t features; /**< Array of enabled features (off_t *). */uint16_t feat_count; /**< Number of enabled features. */off_t data_deps; /**< Array of data dependencies. */uint16_t data_dep_count; /**< Number of data dependencies. */off_t inv_data_deps; /**< Array of inverse data dependencies (off_t *). */uint16_t inv_data_dep_count; /**< Number of inverse data dependencies. */off_t op_deps; /**< Array of operation dependencies. */uint16_t op_dep_count; /**< Number of operation dependencies. */struct {off_t subs; /**< Array of change subscriptions. */uint16_t sub_count; /**< Number of change subscriptions. */} change_sub[SR_DS_COUNT]; /**< Change subscriptions for each datastore. */off_t oper_subs; /**< Array of operational subscriptions. */uint16_t oper_sub_count; /**< Number of operational subscriptions. */off_t notif_subs; /**< Array of notification subscriptions. */uint16_t notif_sub_count; /**< Number of notification subscriptions. */
};
全部的off_t标识这些结构是指向ext SHM的偏移指针。
所以,通过install将模块安装后,这结构就是初始化与注册上。Ext shm是以一个size_t单位开始,这值表示在该SHM分段使用的字节大小。它是由main SHM的 `off_t`指
所指向的数组和字符串表示。首先,在sysrepo有一个sr_conn_state_t结构,它是表示所有全部运行的连接状态,其次是sr_mod_t结构,它是包括安装的各个模块名,依赖,各类订阅,最后是sr_rpc_t。
3、源码分析
此添加shm main的入口代码,将全部模块以lydmod数据形式添加到main SHM中。参考前一章的sr_connect函数,这就是将在与sysrepo连接时,会将全部模块的加载到共享内存中。
sr_error_info_t *
sr_shmmain_add(sr_conn_ctx_t *conn, struct lyd_node *sr_mod)
{sr_error_info_t *err_info = NULL;struct lyd_node *next;sr_mod_t *shm_mod;sr_main_shm_t *main_shm;off_t main_end, ext_end;size_t *wasted_ext, new_ext_size, new_mod_count;/* count how many modules are we going to add *///计算有多少个新的模块需要添加,如果模块在其它的连接已经添加过,该不会计算的/new_mod_count = 0;LY_TREE_FOR(sr_mod, next) {++new_mod_count;}/* remember current SHM and ext SHM end (size) *///记录main SHM与ext SHM的大小 main_end = conn->main_shm.size;ext_end = conn->ext_shm.size;/* enlarge main SHM for the new modules *///为新的模块扩大man SHM的空间,这部分很棒,算的是一种自扩大袜。if ((err_info = sr_shm_remap(&conn->main_shm, conn->main_shm.size + new_mod_count * sizeof *shm_mod))) {return err_info;}/* enlarge ext SHM *///为新的模块扩大ext SHM 空间wasted_ext = (size_t *)conn->ext_shm.addr; //已使用的空间new_ext_size = sizeof(size_t) + sr_shmmain_ext_get_size_main_shm(&conn->main_shm, conn->ext_shm.addr) +sr_shmmain_ext_get_lydmods_size(sr_mod->parent); //需要扩大的空间大小if ((err_info = sr_shm_remap(&conn->ext_shm, new_ext_size + *wasted_ext))) {return err_info;}//sr_shm_remap,将空间映射到连接的SHM分段上。wasted_ext = (size_t *)conn->ext_shm.addr; //新扩大的空间大小。/* add all newly implemented modules into SHM *///添加所有的新的需要实现的模块到SHM中的地址中if ((err_info = sr_shmmain_add_modules(conn->ext_shm.addr, sr_mod, (sr_mod_t *)(conn->main_shm.addr + main_end),&ext_end))) {return err_info;}/* add the new modules number */main_shm = (sr_main_shm_t *)conn->main_shm.addr;main_shm->mod_count += new_mod_count;assert(main_shm->mod_count == (conn->main_shm.size - sizeof *main_shm) / sizeof *shm_mod);/** Dependencies of old modules are rebuild because of possible* 1) new inverse dependencies when new modules depend on the old ones;* 2) new dependencies in the old modules in case they were added by foreign augments in the new modules.* Checking these cases would probably be more costly than just always rebuilding all dependencies.*//* remove all dependencies of all modules from SHM *///处理模块间的依赖,要重构各模块间的依赖,先将之前的依赖关系解除,//然后,为新的模块计算并扩大ext SHM 空间计算//最后,在SHM中为所有的模块添加建立新的依赖。//经过这个处理,各模块间的依赖建立成功。sr_shmmain_del_modules_deps(&conn->main_shm, conn->ext_shm.addr, SR_FIRST_SHM_MOD(conn->main_shm.addr));/* enlarge ext SHM to account for the newly wasted memory */if ((err_info = sr_shm_remap(&conn->ext_shm, new_ext_size + *wasted_ext))) {return err_info;}wasted_ext = (size_t *)conn->ext_shm.addr;/* add all dependencies for all modules in SHM */if ((err_info = sr_shmmain_add_modules_deps(&conn->main_shm, conn->ext_shm.addr, sr_mod->parent->child,SR_FIRST_SHM_MOD(conn->main_shm.addr), &ext_end))) {return err_info;}/* check expected size */SR_CHECK_INT_RET((unsigned)ext_end != new_ext_size + *wasted_ext, err_info);return NULL;
}还有两个核心函数:
sr_shmmain_add_modules(char *ext_shm_addr, struct lyd_node *first_sr_mod, sr_mod_t *first_shm_mod, off_t *ext_end)
//实现将全部的模块以及模块的全部特性都保存于main SHM中。这个函数不会添加data/op/inverse三类依赖sr_shmmain_add_modules_deps(sr_shm_t *shm_main, char *ext_shm_addr, struct lyd_node *first_sr_mod, sr_mod_t *first_shm_mod, off_t *ext_end)
//该函数就是添加各模块间的data/op/inverse 依赖,并保存到manin SHM中。
共享内存间在初始操作,包括信号的创建与初始化,也是在sr_connet函数中处理。sr_connet是plugind与sysrepo的连接入口,SHM是在入口中初始的一种机制,用来保证sysrepo与plugind的通信高效,快速。
先用sysrepo共享内存机制为后面的各类订阅打个底。先了解一下sysrepo的共享内存机理的实现。
正在做一套基于sysrepo的内核态统一纳管平台,比如,按现在的方式,iprout2的使用,只能在Linux通过命令行的方式配置下发,这种方式就是一锤子的买卖,在虚拟化或者云化平台上,配置的持久化,切换上,交互上都不是特别方便。考虑通过sysrepo将iprout2,nftable,strongwan等开源的组件都可以通过sysrepo纳管起来,有兴趣的可以一起搞搞,谢谢~
第四章 sysrepo共享内存机制相关推荐
- Linux_UNIX编程手册-读书笔记-第五十四章(POSIX共享内存)
54.1 概述 POSIX共享内存能够让无关程序共享一个映射区域而无需创建一个相应的映射文件. linux使用挂载与/dev/shm目录下的专用tmpfs文件系统,系统上POSIX共享内存区域占据的内 ...
- JavaScript高级程序设计 第四章---变量 作用域 内存
第四章-变量 作用域 内存 关键字:变量 作用域 内存 本章内容 通过变量使用原始值与引用值 理解执行上下文 理解垃圾回收 4.1 原始值与引用值 ECMAScript 变量可以包含两种不同类型的数据 ...
- Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结
Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...
- 嵌入式Linux系统编程学习之二十三 System V 共享内存机制
文章目录 前言 一.ftok 函数 二.shmget 函数 三.shmat 函数 四.shmdt 函数 五.shmctl 函数 补充 前言 共享内存也是进程间(进程间不需要有继承关系)通信的一种常 ...
- 第四章 区块链共识机制
第四章 区块链共识机制 1.概述 2.工作量证明共识机制 2.2 交易优先级 2.3 数学难题 2.3.1 数学难题 2.3.2 动态调整难度 2.4 最长链原则 2.5 作用 2.6 缺点 3.其它 ...
- linux存储--共享内存机制shm(十四)
共享存储允许两个或多个进程共享一个给定的存储区,是进程间通信最快的一种方式. 不要同时对共享存储空间进行写操作,通常,信号量用于同步共享存储访问. 最简单的共享内存的使用流程 ①ftok函数生成键值 ...
- linux存储--共享内存机制mmap(十二)
mmap基础概念 mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系.实现这样的映射关系后,进程就可以采用指 ...
- linux存储--共享内存机制shm(十三)
实现进程间通信最简单也是最直接的方法就是共享内存--为参与通信的多个进程在内存中开辟一个共享区.由于进程可以直接对共享内存进行读写操作,因此这种通信方式效率特别高,但其弱点是,它没有互斥机制,需要信号 ...
- 共享内存机制——mmap和shm
共享内存是进程间通信的一种方法,常用到的有mmap和shm,下面做一个比较. mmap机制: 在磁盘上建立一个文件,然后把文件内容映射到虚拟内存上,在每个进程的虚拟存储器里面,单独开辟一个空间来进行映 ...
- 多进程编程(四):共享内存
定义: 共享内存(Shared Memory)就是允许两个或多个进程访问同一个内存空间,是在多进程通信的最高效的方式. 操作系统将不同进程之间共享内存安排为同一段物理内存,进程可以将共享内存连接到它们 ...
最新文章
- Oracle Grid Control 11g for linux安装和配置指南
- Vue页面加载使用二级属性的时候报错TypeError: Cannot read property ‘name‘ of undefined“
- C语言程序设计输入x求函数y,C语言程序设计实践(OJ)-初识函数
- Git使用出错:Couldn‘t reserve space for cygwin‘s heap, Win32
- BW之数据源 增量管理DELTA
- Java 11新字符串方法的基准
- Spring Data JPA的持久层
- 数据结构与算法(基于C++语法实现)
- 头条搜索“美丽中国”,你为哪处风景胜地打过Call?
- python中split拆分数组_Python 数组分割
- 剑指offer面试题50. 第一个只出现一次的字符(哈希表)
- 42. 确保lessT与operator小于具有相同的语义
- mappedBy的具体使用及其含义
- 用这几款软件轻松自动识别图片文字,快码住
- 供应链金融你了解多少?
- 如何拆宏碁(acer)笔记本--个人动手更换风扇、清理灰尘
- 猿辅导python编程老师面试_猿辅导辅导老师面试过程➕感受
- 让微信 8.0 「裂开」「炸弹」的特效代码来了
- 嵌入式c语言如何在堆区开辟空间
- 巧用Hosts文件杀掉IE弹出窗口(转)
热门文章
- 开头的单词_学Z字母本义和引申义,初高中Z开头的单词几分钟全部轻松记忆!...
- 图像处理实践 | 水果图像的识别与分类
- 还原文件打开方式为未知应用程序
- Eclipse绿豆沙护眼
- Arm 公司推出了 Mbed linux OS
- 这也能卖?拉美电商平台Mercado Libre上的10种奇葩产品
- 神经系统的组成结构图谱,神经系统的基本结构图
- lol服务器稳定性补偿,lol游戏稳定性补偿皮肤领取
- Android 兼容Android 7拍摄照片/打开相册/选择照片/剪裁照片/显示照片 带demo
- 学习 慕课网【 PHP工程师计划】