钢筋混凝土的UNIXC编程技巧(doc 29页).doc
- 【下载声明】
1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
3. 本页资料《钢筋混凝土的UNIXC编程技巧(doc 29页).doc》由用户(欢乐马)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 钢筋混凝土的UNIXC编程技巧doc 29页 钢筋混凝土 UNIXC 编程 技巧 doc 29
- 资源描述:
-
1、 钢筋混凝土的钢筋混凝土的 UNIX C 编程技巧(一、内存映射表)编程技巧(一、内存映射表) 前言: 大学毕业后从事 unix 上的银行综合业务系统开发工作已有一年半的时间,向众多前辈高手 学习了很多经验和技巧,自己也创新了些好的开发技术,特写出来与奋斗在一线的 unix 程 序员们共享。本人大学时专注于 windows 平台应用开发,工作后才转入 unix 平台,故沿 袭了不少 windows 编码风格。 - 正文: 在一个带有数据库的 unix 系统中进行 E-SQL 嵌入式开发, 必然用到很多混合式编程方式。 当系统对表的 SELECT 操作频繁时,会使数据库效率大幅下降。于是我们很当
2、然的这样设 计: 当应用开始运行时把数据库中需要频繁查询的表装载入共享内存, 通过编写一批共享内 存查询函数实现对表数据的快速查询、定位。这里借用 windows 的一些名词把这一技术命 名为“内存映射表”技术。 内存映射表的格式设计有很多方式, 下面介绍一下我设计的一种格式, 该格式已经应用于某 省级银行信用卡全省大前置系统,取得非常好的效果。 | | | | | | 内存映射表记录条数 | 第一条记录结构单元 | 第二条记录结构单元 | . | | 10 个字节 | 记录结构的大小 | 记录结构的大小 | | | | | | | 共享内存数据存放格式如上图所示。开头的 10 个字节存放内存
3、映射表的记录条数数值,由 于标准 c 的有符号长整数类型最大值约为 21 亿, 所以预留 10 个字节存放 ASCII 编码的记 录条数数值已绰绰有余且取得最大限度值了。 第 11 个字节开始存放数据库表第一条记录对 应的 c 语言结构体,称为一个结构单元。后面依次存放所有数据库表记录形成结构体数组。 一张数据库表装载入一块共享内存,可以通过表名给共享内存的 ipckey 取名。比如“公共 系统参数表”对应的内存映射表的 ipckey 在头文件里这样添加“#define SHMY_KEY_GGXTCS 0x00001138 /* 4408 */“,以便于在程序里引用。 内存映射表共占用共享内存
4、大小为该表记录对应的数据结构体大小乘以记录条数加上10个 字节。比如“公共系统参数表”记录条数为 10 条,表定义如下。那么总占用共享内存大小 =(20+30+40)*10+10=910 个字节。 字段名 字段属性 长度 空值标志 备注 包括中文注释和取值范围 csxh char 20 N.N 参数序号 csz char 30 N.N 参数值 cssm char 40 参数说明 索引 1 unique csxh 内存映射表的操作大致有装载和查询两种操作, 其它还可以有简单的更新操作。 考虑到每个 内存映射表的操作大致一样以及以某个关键字段查询、更新操作的相似性,再以“公共系统 参数表”我这样设
5、计内存映射表的操作函数原形: int LoadMapGGXTCS(); int FetchMapGGXTCS ( void *pvCondValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG , int (* REPLACE_FUNCNAME_COMPARE_PROC) ( void *pvCondValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); int UpdateMapGGXTCS ( void *pvCondValue , void *pvUpdateValu
6、e , int (* REPLACE_FUNCNAME_UPDATE_PROC) ( void *pvCondValue , void *pvUpdateValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); 两个函数内所有涉及到具体表名、结构体名、回调函数名我都已宏的方式替换掉,这样做的 好处是可以形成代码模板, 如果以后要添加一张表的映射只要复制代码模板到实现文件的最 后面, 把代码模板最前面的宏定义成具体的值。 代码模板最后面把所有用过的宏都反定义掉, 不妨碍后面的程序使用。 装载表函数我不用多说了,即把表数据装载入共享内
7、存,不需要参数。 查询函数第一个参数为关键字段值,与 REPLACE_FUNCNAME_COMPARE_PROC 回调 函数配合使用。参数类型为 void*类型,这样就可以兼容所有类型的数据甚至是结构体、共 用体, 额外麻烦的只是把变量传入前强制传换成 void*, 在回调函数里再转换回具体的变量 类型。第二个参数是结构体宏,用于函数成功返回时把符合要求的记录结构体返回。第三个 参数是指向回调函数的指针, 其作用是针对某一关键字段, 分别取出共享内存里的每条记录 进行比较,当条件符合时,回调函数返回 0,否则返回 1,这样可以不改变外层遍历函数的 条件下,使用不同判断方式、不同的判断值对内存映
8、射表中所有记录进行遍历。 本文最后附件中附有装载、 查询和更新三个内存映射表的代码模板, 由于完全采用参数化宏 替换方式设计,甚至可以不加修改的立即应用到您的系统中去。 下面跳跃的介绍一下查询函数极其回调函数的操作原理。 更新函数原理与之相似, 结构稍稍 复杂一些,重点是回调函数。 查询函数 . 遍历内存映射表中所有结构记录 调用遍历函数最后一个参数即回调函数指针(条件值,当前结构记录); 如果回调函数返回 0,即条件符合且更新成功 复制内存映射表中当前结构记录内容到 pREPLACE_STRUCT_ARG 指针空间里,输出给 用户 跳出遍历; 偏移到内存映射表中下一条结构记录; . 返回回调
9、函数的返回值 查询回调函数(条件值,内存映射表中当前结构记录) 把便利函数传入的条件值强制转换成 char*类型; 与内存映射表中当前结构记录的 csxh 进行比较,如果相等即找到 返回 0; 否则 返回 1; 查询函数的使用示例 . /* 获取 对帐场次 */ iRt = FetchMapGGXTCS( (void *)“dzcc“ , if( iRt != 0 ) printf( “获取对帐场次 失败“ ); else printf( “当前对帐场次为%s“ , stGgxtcs.csz ); . 使用该设计通过创建与数据库表映射的共享内存数据提高对数据库静态表 (运行时数据内容 不改变或
10、者只做少量更新的表)的查询访问速度,而不需要额外占用数据库宝贵的效率,尤 其在一个对数据库操作频繁的系统中能很大程度的提高整个系统的运行效率。 本设计也有不 足之处,主要是只能代替数据库简单的 SELECT 操作和 UPDATE 操作,不支持 INSERT、 DELETE 操作,不过对于一些静态表的查询使用已经足够了,不是吗 _ - 附件一、内存映射表 代码模块(以“公共系统参数表”为例) /* * 获取 公共系统参数表 内存映射表 相应记录 * */ #define REPLACE_STRUCT_TYPE ggxtcs #define REPLACE_STRUCT_ARG stGgxtcs
11、#define REPLACE_SHEKEY SHMY_KEY_GGXTCS #define REPLACE_TABLENAME ggxtcs #define REPLACE_TABLEDESC “公共系统参数表“ #define REPLACE_CURSORNAME curGGXTCS #define REPLACE_DBVAR R_GGXTCS #define REPLACE_DBVARFUNC pubVtoSGgxtcs #define REPLACE_FUNCNAME_FETCH “FetchMapGGXTCS“ #define REPLACE_FUNCNAME_LOAD “LoadM
12、apGGXTCS“ #define REPLACE_FUNCNAME_COMPARE_PROC CompareKeyFromGGXTCSProc #define REPLACE_FUNCNAME_UPDATE_PROC UpdateValueFromGGXTCSProc int FetchMapGGXTCS ( void *pvCondValue , struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG , int (* REPLACE_FUNCNAME_COMPARE_PROC) ( void *pvCondValue , struct REPLAC
13、E_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); int iReturnValue; struct REPLACE_STRUCT_TYPE *pmpREPLACE_STRUCT_ARG; char *pmp; char acRecordAmount11; long lRecordAmount; long l; _IPC_ID_T ipcid; /* 判断 内存映射表 是否存在 */ iReturnValue = IPCIsShareMemoryExist( REPLACE_SHEKEY ); if( iReturnValue = IPC_SHAREMEMORY_R
14、ETURN_ISNT_EXIST ) /* 若不存在 则创建之 */ iReturnValue = LoadMapGGXTCS(); if( iReturnValue != 0 ) WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 创建 内存映射表 “REPLACE_TABLEDESC“ 失败 错误码%d errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_,
15、iReturnValue, errno ); return -1; /* 打开 内存映射表 */ ipcid = IPCOpenShareMemory( REPLACE_SHEKEY ); if( ipcid 0 ) /* 打开失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 打开 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256
16、 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -2; /* 连接 内存映射表 地址 */ pmp = IPCAttachShareMemory( ipcid ); if( pmp = NULL ) /* 连接失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 连接 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeS
17、tringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ), _LINE_, errno ); return -3; memset( acRecordAmount , 0x00 , sizeof( acRecordAmount ) ); strncpy( acRecordAmount , pmp , 10 ); lRecordAmount = atol( acRecordAmount ); pmpREPLACE_STRUCT_ARG = (struct REPLACE_STRUCT_TYPE *)( pmp + 10 ) ; /* 搜寻 内存映射表 */ for( l=
18、0 ; llRecordAmount ; l+ ) /* 调用搜寻回调函数 */ iReturnValue = REPLACE_FUNCNAME_COMPARE_PROC( pvCondValue , pmpREPLACE_STRUCT_ARG ) ; if( iReturnValue != 1 ) memset( pREPLACE_STRUCT_ARG , 0x00 , sizeof( struct REPLACE_STRUCT_TYPE ) ); memcpy( pREPLACE_STRUCT_ARG , pmpREPLACE_STRUCT_ARG , sizeof(struct REPL
19、ACE_STRUCT_TYPE) ); break; pmpREPLACE_STRUCT_ARG + ; /* 断开 内存映射表 地址连接 */ IPCDetachShareMemory( pmp ); return iReturnValue; /* * 更新 公共系统参数表 内存映射表 * */ int UpdateMapGGXTCS ( void *pvCondValue , void *pvUpdateValue , int (* REPLACE_FUNCNAME_UPDATE_PROC) ( void *pvCondValue , void *pvUpdateValue , struc
20、t REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG ) ); int iReturnValue; struct REPLACE_STRUCT_TYPE *pmpREPLACE_STRUCT_ARG; char *pmp; char acRecordAmount11; long lRecordAmount; long l; _IPC_ID_T ipcid; /* 判断 内存映射表 是否存在 */ iReturnValue = IPCIsShareMemoryExist( REPLACE_SHEKEY ); if( iReturnValue = IPC_SHARE
21、MEMORY_RETURN_ISNT_EXIST ) /* 若不存在 则创建之 */ iReturnValue = LoadMapGGXTCS(); if( iReturnValue != 0 ) WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 创建 内存映射表 “REPLACE_TABLEDESC“ 失败 错误码%d errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuffer , 256 , “%Y-%m-%d %H:%M:%S“ ),
22、_LINE_, iReturnValue, errno ); return -1; /* 打开 内存映射表 */ ipcid = IPCOpenShareMemory( REPLACE_SHEKEY ); if( ipcid 0 ) /* 打开失败,写出错日志,函数返回 */ WriteLog( gacLogFilename, “%s | “REPLACE_FUNCNAME_FETCH“ | “LOG_LINELEN“ | 打开 内存映射表 “REPLACE_TABLEDESC“ 失败 errno%d,请重启应用n“, GetLocalTimeString( gacTimeStringBuff
展开阅读全文