资源预览内容
第1页 / 共29页
第2页 / 共29页
第3页 / 共29页
第4页 / 共29页
第5页 / 共29页
第6页 / 共29页
第7页 / 共29页
第8页 / 共29页
第9页 / 共29页
第10页 / 共29页
亲,该文档总共29页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
钢筋混凝土的UNIX C编程技巧(一、内存映射表)、, 、刖百:大学毕业后从事unix上的银行综合业务系统开发工作已有一年半的时间,向众多前辈高手学习了很多 经验和技巧,自己也创新了些好的开发技术,特写出来与奋斗在一线的unix程序员们共享。本人大学 时专注于windows平台应用开发,工作后才转入unix平台,故沿袭了不少windows编码风格。正文:在一个带有数据库的unix系统中进行E6QL嵌入式开发,必然用到很多混合式编程方式。当系统 对表的SELECT操作频繁时,会使数据库效率大幅下降。于是我们很当然的这样设计:当应用开始运 行时把数据库中需要频繁查询的表装载人共享内存,通过编写一批共享内存查询函数实现对表数据的 快速查询、定位。这里借用windows的一些名词把这一技术命名为“内存映射表”技术。内存映射表的格式设计有很多方式,下面介绍一下我设计的一种格式,该格式已经应用于某省级银 行信用卡全省大前置系统,取得非常好的效果。I内存映射表记录条数I第一条记录结构单元I第二条记录结构单元I 10个字节|记录结构的大小I记录结构的大小IIIIII共享内存数据存放格式如上图所示。开头的10个字节存放内存映射表的记录条数数值,于标准C的有符号长整数类型最大值约为21亿,所以预留10个字节存放ASCII编码的记录条数数II值已绰绰有余且取得最大限度值了。第1 1个字节开始存放数据库表第一条记录对应的C语言结构体,称为一个结构单元。后面依次存放所有数据库表记录形成结构体数组。一张数据库表装载入一块 共享内存,可以通过表名给共享内存的ipckey取名。比如“公共系统参数表”对应的内存映射表的 ipckey 在头文件里这样添加 #define SHMY_KEY_GGXTCS 0x00001138 /* 4408 */,以便于在程序 里引用。内存映射表共占用共享内存大小为该表记录对应的数据结构体大小乘以记录条数加上10个字节。比 如“公共系统参数表”记录条数为10条,表定义如下。那么总占用共享内存大小 =(20+30+40)*10+10=910 个字节。字段名字段属性长度空值标志备注包括中文注释和取值范围struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG参数序号参数值参数说明csxh char 20 N.Ncsz char 30 N.Ncssm char 40索弓 | 1 unique csxh内存映射表的操作大致有装载和查询两种操作,其它还可以有简单的更新操作。考虑到每个 内存映射表的操作大致一样以及以某个关键字段查询、更新操作的相似性,再以“公共系统 参数表”我这样设计内存映射表的操作函数原形:int LoadMapGGXTCS();int FetchMapGGXTCS ( void *pvCondValue ,struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG , int (* REPLACE_FUNCNAME_COMPARE_PROC)(void *pvCondValue ,);int UpdateMapGGXTCS ( void *pvCondValue ,void *pvUpdateValue ,int (* REPLACE_FUNCNAME_UPDATE_PROC)(void *pvCondValue ,void *pvUpdateValue ,struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG) );两个函数内所有涉及到具体表名、结构体名、回调函数名我都已宏的方式替换掉,这样做的 好处是 可以形成代码模板,如果以后要添加一张表的映射只要复制代码模板到实现文件的最 后面,把代码模 板最前面的宏定义成具体的值。代码模板最后面把所有用过的宏都反定义掉,不妨碍后面的程序使用。 装载表函数我不用多说了,即把表数据装载人共享内存,不需要参数。查询函数第一个参数为关键字段 值,与REPLACE_FUNCNAME_COMPARE_PROC回调 函数配合使用。参数类型为void*类型, 这样就可以兼容所有类型的数据甚至是结构体、共 用体,额外麻烦的只是把变量传入前强制传换成 void*,在回调函数里再转换回具体的变量类型。第二个参数是结构体宏,用于函数成功返回时把符合要求的记录结构体返回。参数 第三个 是指向回调函数的指针,其作用是针对某一关键字段,分别取出共享内存里的每条记录进行比较,当条件符合时,回调函数返回0,否则返回1,这样可以不改变外层遍历函数的条件下,使用不同判断方式、不同的判断值对内存映射表中所有记录进行遍历。本文最后附件中附有 装载、查询和更新三个内存映射表的代码模板,由于完全采用参数化宏替换方式设计,甚至可以不 加修改的立即应用到您的系统中去。下面跳跃的介绍一下查询函数极其回调函数的操作原理。更新函 数原理与之相似,结构稍稍复杂一些,重点是回调函数。查询函数遍历内存映射表中所有结构记录调用遍历函数最后一个参数即回调函数指针(条件值,当前结构记录);如果回调函数返回0,即条件符合且更新成功(复制内存映射表中当前结构记录内容到pREPLACE_STRUCT_ARG指针空间里,输出给用户跳出遍历;)偏移到内存映射表中下一条结构记录;返回回调函数的返回值)查询回调函数(条件值,内存映射表中当前结构记录)把便利函数传入的条件值强制转换成char*类型;与内存映射表中当前结构记录的csxh进行比较,如果相等即找到返回0;否则返回1;查询函数的使用示例/*获取对帐场次*/iRt = FetchMapGGXTCS( (void *)dzccH, &stGgxtcs , &CompareKeyFromGGXTCSWhereCSXHProc );if( iRt != 0 )printf( *,获取对帐场次 失败);else printf(H 当前对帐场次为%sH, stGgxtcs.csz );使用该设计通过创建与数据库表映射的共享内存数据提高对数据库静态表不改变运行时数据内容或者只做少量更新的表)的查询访问速度,而不需要额外占用数据库宝贵的效率,尤其在一个对数据库操作频繁的系统中能很大程度的提高整个系统的运行效率。本设计也有不 足之处,主要是只能代替数据库简单的SELECT操作和UPDATE操作,不支持INSERT、DELETE操作,不过对于一些静态表的查询使用已经足够了 ,不是吗附件一、内存映射表代码模块(以“公共系统参数表”为例)*获取公共系统参数表内存映射表相应记录*/#define REPLACE_STRUCT_TYPE ggxtcs#define REPLACE_STRUCT_ARG stGgxtcs#define REPLACE_SHEKEY SHMY_KEY_GGXTCS#define REPLACE_TABLENAME ggxtcs#define REPLACE_TABLEDESC n 公共系统参数表”#define REPLACE_CURSORNAME curGGXTCS#define REPLACE_DBVAR R_GGXTCS#define REPLACE_DBVARFUNC pubVtoSGgxtcs#define REPLACE_FUNCNAME_FETCH TetchMapGGXTCS,#define REPLACE_FUNCNAME_LOAD ToadMapGGXTCS1#define REPLACE_FUNCNAME_COMPARE_PROCCompareKeyFromGGXT CSProc#define REPLACE_FUNCNAME_UPDATE_PROC UpdateValueFromGGXTCSProc intFetchMapGGXTCS ( void *pvCondValue ,struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG , int (*REPLACE_FUNCNAME_COMPARE_PROC)(void *pvCondValue ,struct REPLACE_STRUCT_TYPE *pREPLACE_STRUCT_ARG);(int iReturnValue;struct REPLACE_STRUCT_TYPE *pmpREPLACE_STRUCT_ARG;char *pmp;char acRecordAmount11;long IRecordAmount;long I;_IPC_ID_T ipcid;/* 判断 内存映射表 是否存在 */ iReturnValue = IPCIsShareMemoryExist( REPLACE_SHEKEY );if( iReturnValue = IPC_SHAREMEMORY_RETURN_ISNT_EXIST )/*若不存在则创建之*/iReturnValue = LoadMapGGXT CS();if( iReturnValue != 0 ) (WriteLog( gacLogFilename,”s | REPLACE_FUNCNAME_FETCH, | LOG_LINELENH |创建 内存映射表*REPLACE_TABLEDESC-失败错误码%d errno%d,请重启应用 n,GetLocalTimeString( gacTimeStringBuffer, 256 , %Y-%m-%d %H:%M:%S),LINE,iReturnValue, errno );return -1;/*打开内存映射表*/ipcid = IPCOpenShareMemory( REPLACE_SHEKEY );if( ipcid 0 )WriteLog( gacLogFilename,打开内存映射表s | nREPLACE_FUNCNAME_FETCHn | ,LOG_LINELENH | ,REPLACE_TABLEDESCH 失败 errno%d,请重启应用 n”,/*打开失败,写出错日志,函数返回*/GetLocalTimeString( gacTimeStringBuffer, 256 , %Y-%m-%d %H:%M:%S), LINE, errno );return -2;/*连接内存映射表地址*/pmp = IPCAttachShareMemory( ipcid );if( pmp = NULL )/*连接失败,写出错日志,函数返回*/WriteLog( gacLogFilename,”s | REPLACE_FUNCNAME_FETCHTLOG_LINELEN” |连接 内存映射表”REPLACE_TABLEDESC” 失败 errno%d,请重启应用 n”,GetLocalTimeString( gacTimeStringBuffer, 256 , %Y-%m-%d %H:%M:%S), LINE, errno );return -3;memset( acRecordAmount, 0x0
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号