专利名称:防止内存泄露和内存多次释放的内核模块内存管理方法
技术领域:
本发明涉及操作系统内核模块的内存管理方法,具体涉及一种防止操作系统中具 有独立功能的内核模块发生内存泄露和多次内存释放故障的内核模块的内存管理方法。
背景技术:
操作系统内核是实现多种功能的系统,功能固有的独立特性和内核系统所需的扩 展特性,使得模块化成为操作系统内核的重要构成方法。通常内核由多个完成不同功能的 模块组成,每个模块具有独立入口和出口,具有闭环的控制流。内存是内核系统运行过程中 最为稀缺的资源,动态按需分配是操作系统内核以有限内存资源满足无限应用需求的主要 方法,系统内的各个功能模块在运行过程需要的部分内存通过内核内存管理系统提供的内 存分配函数获得,该部分内存要求模块退出时进行释放,部分模块程序忽略内存释放操作 使得未被使用的内存仍然游离于内核内存管理之外,引发内存泄露问题,严重阻碍内存资 源有效利用,造成系统性能下降。另外一方面,部分模块程序会多次释放同一块内存,造成 内存系统的混乱,甚者导致系统的崩溃。如图1所示,内核模块由于被操作系统加载运行而 启动该内核模块生命周期,内核模块在生命周期中为完成自己的特定功能需要按需请求系 统分配内存,然后使用内存完成特定功能的任务逻辑,在使用完内存后将内存释放回系统, 最后当内核模块完成自己的使命后,系统卸载内核模块,从而终止内核模块的生命周期,在 内核模块的运行过程中的一段时间会使用内存,用完释放后内存可以被其他模块使用。如 图2所示,内核模块由于被操作系统加载运行而启动该内核模块生命周期,内核模块在完 成自己的特定功能时按需从操作系统申请内存,在使用完内存后内核模块多次调用内存释 放操作将同一块内存释放回系统中,发生多次内存释放故障,造成内核模块内存管理系统 的混乱。如图3所示,在生命周期内内核模块为完成自己的特定功能时按需从系统申请内 存,但是在内存使用完毕后内核模块并没有调用内存释放操作将其还给内核系统。内核模 块退出后,已经不需要使用先前申请的内存,但是这块内存仍然无法给内核其他模块使用, 这种情况称为内存泄露。操作系统一般通过垃圾回收算法来对内存进行回收。垃圾回收算法是软件系统中 一种集中式的内存泄露解决方法,主要思想是系统运行独立的垃圾回收线程,在系统空闲 的时候,该垃圾回收线程从系统的根集出发,定位所有在使用的内存,并将总内存池中未被 使用的内存回收。垃圾回收算法虽然可以实现异步的非精确性的内存回收,但是由于垃圾 回收线程运行受限于系统的忙闲程度,仍然无法彻底解决内存泄露问题。
发明内容
本发明要解决的技术问题为提供一种可防止内核模块发生内存泄露和多次内存 释放、内存定位能力好、操作系统忙闲程度低、占用资源少、内存足迹小、适应性好的防止内 存泄露和内存多次释放的内核模块内存管理方法。为了解决上述技术问题,本发明采用的技术方案为一种防止内存泄露和内存多次释放的内核模块内存管理方法,其实施步骤如下1)建立用于记录该内核模块内存分配记录的记录数组;2)当内核模块请求系统分配内存时,往所述记录数组中添加与分配内存相关联的 内存分配记录;3)当内核模块请求系统释放内存时,在所述记录数组中查找与待释放内存相关联 的内存分配记录,如果存在关联的内存分配记录则执行内存释放、并删除该内存分配记录; 如果不存在关联的内存分配记录则表明释放了未曾申请的内存、发生了释放错或多次释放 的情况。4)当内核模块退出时,扫描记录数组,如果记录数组中仍留有内存分配记录,则根 据内存分配记录将其关联的内存进行逐一释放,并最终清除记录数组。作为本发明防止内存泄露和内存多次释放的内核模块内存管理方法的进一步改 进所述记录数组包括至少一个可扩展的数组单元,所述数组单元由多个用于存储内 存分配记录的记录槽和一个用于扩展数组单元的扩展槽组成,所述步骤1)中初始建立的 记录数组中仅包含一个数组单元,所述步骤幻中当一个数组单元的记录槽的数量不足以 存储内存分配记录时,通过扩展槽扩展出新的数组单元来存储内存分配记录。所述记录槽由用于存储内存位置信息的第一指针域和用于存储当前记录槽使用 状态信息的第一状态域组成,所述扩展槽由用于存储下一个数组单元位置信息的第二指针 域和用于存储当前数组单元中记录槽的使用状态信息和当前数组单元的扩展状态信息的 第二状态域组成,所述第一状态域的状态包括已使用和未使用两种状态,所述第二状态域 的状态包括记录槽为空、记录槽已满和数组单元已扩展三种状态。所述步骤幻中添加内存分配记录时,首先读取第一个数组单元的扩展槽的第二 状态域;然后针对第二状态域执行判断处理,如果当前数组单元仍有空的记录槽,则将内存 分配记录写入空的记录槽,如果数组单元写入内存分配记录后再无空的记录槽,则将扩展 槽的第二状态域标记为已满;如果当前数组单元的记录槽已满,则建立新数组单元,将当前 数组单元中扩展槽的第二状态域与新数组单元建立关联,然后将内存分配记录写入新数组 单元的第一个空的记录槽;如果当前数组单元的扩展槽已经扩展出新数组单元,则将下一 个数组单元作为当前的数组单元,返回上述针对第二状态域执行判断处理。所述步骤幻中在执行内存释放时,首先在记录数组的所有数组单元查找与待释 放内容相关联的内存分配记录,然后根据查找到内存分配记录对应记录槽的第一状态域执 行判断处理,如果第一状态域为已使用状态,则终止查询与待释放内容相关联的内存分配 记录;如果第一状态域为未使用状态,则继续查找与待释放内容相关联的内存分配记录,如 果找到则继续返回上述针对第一状态域执行判断处理,否则终止查询与待释放内容相关联 的内存分配记录。所述步骤幻中删除内存分配记录是指将该内存分配记录标记为未使用状态,所 述查找内存分配记录时,如果找到内存分配记录且该内存分配记录已经被标记为未使用状 态,则输出发生多次内存释放的报警信息;所述步骤4)中,如果扫描记录数组时记录数组 中仍留有内存分配记录,则输出发生内存泄露的报警信息。本发明具有下述优点
1、本发明可以有效防止同一内存记录发生多次释放,即使内核模块没有请求释放 内存,仍然可以通过内核模块退出后的执行步骤释放内存,可以有效防止内存泄露,不需要 专门的线程维护,不依赖于操作系统的忙闲程度,可以解决操作系统中内核模块的内存管 理问题,带有模块内存泄露定位能力,不仅可以检测是否存在内存泄漏情况,还可以确认泄 漏内存的地址,并且具有防止释放无效内存的功能,具有内存泄露定位能力好、操作系统忙 闲程度低、占用资源少、内存足迹小、适应性好的优点。2、记录数组包括至少一个数组单元,数组单元通过扩展槽形成可扩展的数组链结 构,因此使用非常灵活,既可以满足内存足迹小的内核模块的记录经济性,也可以保证内存 足迹大的内核模块的记录需求,可检测多种模块的内存泄露,有效满足操作系统内核可用 性的需要,具有占用资源少、内存足迹小、适应性好的优点。3、记录槽包括第一状态域,因此可以通过读取第一状态域来获取记录槽的状态, 可以方便检测是否存在多次发生内存释放鼓掌;4、扩展槽由第二指针域和第二状态域组成,第二状态域用于存储当前数组单元的 记录槽的使用状态和下一个数组单元的状态信息,因此可以方便实现当前数组单元的信息 获取以及所有数组单元的依序查找,查找效率更高,定位能力更好。5、在删除该内存分配记录时将该内存分配记录标记为已删除,当找到与待释放内 存相匹配的内存分配记录且该内存分配记录已经置为已删除标记,则输出发生多次内存释 放的报警信息,可以有效监控操作系统的内核模块的多次内存释放信息;如果扫描记录数 组时找到仍有内存分配记录,则输出发生内存泄露的报警信息,从而可以方便定位内核模 块发生多次内存释放和内存泄露的故障信息,便于对操作系统的内核模块进行改进。
图1为现有技术内核模块正常执行的流程示意图;图2为现有技术内核模块执行产生多次内存释放的流程原理示意图;图3为现有技术内核模块执行产生内存泄露的流程原理示意图;图4为本发明实施例的流程示意图;图5为本发明实施例的记录数组的结构示意图;图6为本发明实施例的记录槽的结构示意图;图7为本发明实施例的扩展槽的结构示意图;图8为本发明实施例的记录槽的状态变化示意图;图9为本发明实施例的扩展槽的状态变化示意图;图10为本发明实施例的记录数组初始化的流程示意图;图11为本发明实施例在内存分配时的记录修改流程示意图;图12为本发明实施例在内存回收时的记录修改流程示意图。图例说明1、数组单元;11、记录槽;111、第一指针域;112第一状态域;12、扩展 槽;121、第二指针域;122、第二状态域。
具体实施例方式如图4所示,本发明实施例的防止内存泄露和内存多次释放的内核模块内存管理方法的实施步骤如下1)建立用于记录该内核模块内存分配记录的记录数组;2)当内核模块请求系统分配内存时,往记录数组中添加与分配内存相关联的内存 分配记录;3)当内核模块请求系统释放内存时,在记录数组中查找与待释放内存相关联的内 存分配记录,如果存在关联的内存分配记录则执行内存释放、并删除该内存分配记录;4)当内核模块退出时,扫描记录数组,如果记录数组中仍留有内存分配记录,则根 据内存分配记录将其关联的内存进行逐一释放,并最终清除记录数组。本实施例中,在内核模块现有的系统内存分配逻辑中添加了步骤幻,在内核模块 现有的系统内存释放逻辑中添加了步骤幻,在内核模块退出时增加了步骤4),从而可以有 效防止操作系统中内核模块从加载到退出的过程中发生内存泄露和内存多次释放。如图5所示,记录数组包括至少一个可扩展的数组单元1,数组单元1由多个用于 存储内存分配记录的记录槽11和一个用于扩展数组单元1的扩展槽12组成,步骤1)中初 始建立的记录数组中仅包含一个数组单元1,步骤2、中当一个数组单元1的记录槽11的 数量不足以存储内存分配记录时,通过扩展槽12扩展出新的数组单元1来存储内存分配记 录。记录槽11用于存储内存位置信息和当前记录槽11使用状态信息,扩展槽12用于存储 存储下一个数组单元1位置信息和当前数组单元1中记录槽11的使用状态信息和当前数 组单元1的扩展状态信息,其中内存位置信息和下一个数组单元1位置信息均为内存指针。如图6和图7所示,记录槽11由用于存储内存位置信息的第一指针域111和用于 存储当前记录槽11使用状态信息的第一状态域112组成,扩展槽12由用于存储下一个数 组单元1位置信息的第二指针域121和用于存储当前数组单元1中记录槽11的使用状态 信息和当前数组单元1的扩展状态信息的第二状态域122组成,第一状态域112的状态包 括已使用和未使用两种状态,第二状态域122的状态包括记录槽11为空、记录槽11已满和 数组单元1已扩展三种状态。如图8所示,本实施例中第一状态域112采用Inuse表示已使用状态,Unused表 示未使用状态。第一指针域111存在两种状态存在内存指针和NULL。记录槽11初始化 (INIT)时,第一指针域111为NULL,第一状态域112为Unused ;记录槽11存在内存分配 记录(OCCUPIED)时,第一指针域111中为内存指针,第一状态域112为huse ;记录槽11 在释放后(FREE)时,第一指针域111中仍然记录有已经释放的内存指针,第一状态域112 为Unused。如图9所示,本实施例中第二状态域122采用EMPTY表示记录槽11为空、采用 FULL表示记录槽11满、采用INUSE表示数组单元1已扩展。扩展槽12初始化(INIT)时, 第二指针域121为NULL,第二状态域122为EMPTY。若当前数组单元1的所有记录槽11已 满(FULL)时,第二指针域121为NULL,第二状态域122为FULL。若当前数组单元1扩展出 新的数组单元I(EXPAND)后,则第二指针域121为扩展出的下一个数组单元1的内存指针, 第二状态域122为INUSE。本实施例中,记录槽11和扩展槽12都具有相同的数据结构。记录槽11的结构类 型定义如下Struct plog{void*P
int status}扩展槽12的结构类型定义如下Struct elog{void*Pint status}其中P为指针类型变量,status为整数类型变量,P用于记录第一指针域111或者 第二指针域121的指针值,而status用于记录第一状态域112或者第二状态域122的状态 信息。本实施例中,对于第一状态域112而言,0表示Unused,1表示huse ;对于第二状态 域122而言,0表示EMPTY,1表示FULL,2表示INUSE。本实施例的数组单元1由S个记录槽11和一个扩展槽12组成,因此一个数组单 元1的长度为s+1,S可以根据内核模块请求分配内存的平均数目决定,该数据可以通过实 测运行的操作系统来统计内核模块的平均内存申请数来确定。如以Ploghead数组表示一 个数组单元1,则第1 S个存储空间为记录槽11,第S+1个存储空间为扩展槽12。如图 10所示,在进行初始化时,首先分配S+1长度的内存空间作为记录体,然后使用一个循环将 数组单元1的所有记录槽11和扩展槽12进行初始化,将第一指针域111赋值为NULL,将 第一状态域112赋值为Unused,将第二指针域121赋值为NULL,将第二状态域122赋值为 EMPTY,最后调用内核模块入口,开始对内核模块进行初始化。本实施例在步骤幻中添加内存分配记录时,首先读取第一个数组单元1的扩展槽 12的第二状态域122 ;然后针对第二状态域122执行判断处理,如果当前数组单元1仍有空 的记录槽11,则将内存分配记录写入空的记录槽11,如果数组单元1写入内存分配记录后 再无空的记录槽11,则将扩展槽12的第二状态域122标记为已满;如果当前数组单元1的 记录槽11已满,则建立新数组单元1,将当前数组单元1中扩展槽12的第二状态域122与新 数组单元1建立关联,然后将内存分配记录写入新数组单元1的第一个空的记录槽11 ;如 果当前数组单元1的扩展槽12已经扩展出新数组单元1,则将下一个数组单元1作为当前 的数组单元1,返回上述针对第二状态域122执行判断处理。操作系统中,内存分配函数通
常具有void*malloc(int size,......)的形式,其中size为需要分配的内存大小;void*
为系统返回分配的内存地址。如图11所示,Ploghead代表一个数组单元l,ploglist为用 于处理的数组变量,本实施例在添加内存分配记录时的详细步骤如下(1)、将当前的ploghead赋值给ploglist,其效果为将数组变量ploglist指向当 前的数组单元1。(2)、判断 ploglist[S]的状态如果ploglist中存在空记录槽11,获得该记录槽11并将内存地址记录到该空 记录槽11中,同时将空槽标记为^use即已使用,如果发现是数组中的最后一个空槽,将 ploglist[S]的状态域置为FULL,表示ploglist的所有记录槽11已满。如果ploglist的记录槽11已满,并且还未扩展出新的数组单元1,将 ploglist[S]的状态置为huse,表明已经扩展,进行扩展数组单元1 首先分配一块新的数 组单元1,将数组记录在ploghead[S]的指针域。将新的数组单元1的第一项作为空记录槽11,内存地址记录到该空记录槽11中,将空记录槽11标记为huse。如果ploglist已经扩展出新的数组,则将ploglist指向扩展的数组单元1对应 的ploghead,重新跳转执行步骤(2)。本实施例在步骤幻中在执行内存释放时,首先在记录数组的所有数组单元1查找 与待释放内容相关联的内存分配记录,然后根据查找到内存分配记录对应记录槽11的第 一状态域112执行判断处理,如果第一状态域112为已使用状态,则终止查询与待释放内容 相关联的内存分配记录;如果第一状态域112为未使用状态,则继续查找与待释放内容相 关联的内存分配记录,如果找到则继续返回上述针对第一状态域112执行判断处理,否则 终止查询与待释放内容相关联的内存分配记录。如图12所示,ploghead代表一个数组单 元1,ploglist为用于处理的数组变量,Q为待释放的内存,本实施例在执行内存释放前的 详细步骤如下①将ploghead 赋值给 ploglist ;②判断Q是否和ploglist中元素的第一指针域111的值匹配,找到匹配的第一指 针域111后则对第一状态域112进行判断如果对应的第一状态域112为huse,表示释放已分配内存,转入执行步骤③;如果对应的第一状态域112为Unused,转入执行步骤④;如果未找到匹配的指针,表示此内存从前并没有被分配过,发生了错误的释放操 作,转入执行步骤⑤。③将第一指针域111对应第一状态域112的值置为Unused,调用操作系统的内存 释放逻辑将内存释放回收至操作系统的内存管理池,这个操作保证被模块正确释放内存操 作被记录下来,最后转入执行步骤⑥。④继续查找,直到找到匹配的Q,而且对应的Matus为huse的记录项,此时将Q 对应Matus的置为Unused,调用后续的内存释放逻辑将内存释放回收至操作系统的内存 管理池;如果没有找到,表明多次释放相同的指针,发生了错误的释放,报错后可以直接返 回而不调用后续的释放逻辑,最后转入执行步骤⑥。⑤报错后直接返回,不调用后续的释放逻辑,最后转入执行步骤⑥。
⑥返回执行内核模块的出口函数。本实施例中,步骤幻中删除内存分配记录是指将该内存分配记录标记为未使用 状态,查找内存分配记录时,如果找到内存分配记录且该内存分配记录已经被标记为未使 用状态,则输出发生多次内存释放的报警信息;步骤4)中,如果扫描记录数组时记录数组 中仍留有内存分配记录,则输出发生内存泄露的报警信息。本实施例的步骤4)中扫描记录数组是通过查找未被清除为Inuse的第一状态域。 如果存在^use的第一状态域,则表明内存泄露存在,然后根据内存分配记录调用系统的 free函数将其关联的内存进行逐一释放,并最终清除记录数组。以上仅是本发明的优选实施方式,本发明的保护范围并不仅局限于上述实施例, 凡属于本发明思路下的技术方案均属于本发明的保护范围。应当指出,对于本技术领域的 普通技术人员来说,在不脱离本发明原理前提下的若干改进和润饰,应视为本发明的保护 范围。
9
权利要求
1.一种防止内存泄露和内存多次释放的内核模块内存管理方法,其特征在于其实施步 骤如下1)建立用于记录该内核模块内存分配记录的记录数组;2)当内核模块请求系统分配内存时,往所述记录数组中添加与分配内存相关联的内存 分配记录;3)当内核模块请求系统释放内存时,在所述记录数组中查找与待释放内存相关联的内 存分配记录,如果存在关联的内存分配记录则执行内存释放、并删除该内存分配记录;4)当内核模块退出时,扫描记录数组,如果记录数组中仍留有内存分配记录,则根据内 存分配记录将其关联的内存进行逐一释放,并最终清除记录数组。
2.根据权利要求1所述的防止内存泄露和内存多次释放的内核模块内存管理方法,其 特征在于所述记录数组包括至少一个可扩展的数组单元(1),所述数组单元(1)由多个用 于存储内存分配记录的记录槽(11)和一个用于扩展数组单元⑴的扩展槽(12)组成,所 述步骤1)中初始建立的记录数组中仅包含一个数组单元(1),所述步骤幻中当一个数组单 元(1)的记录槽(11)的数量不足以存储内存分配记录时,通过扩展槽(1 扩展出新的数 组单元(1)来存储内存分配记录。
3.根据权利要求2所述的防止内存泄露和内存多次释放的内核模块内存管理方法,其 特征在于所述记录槽(11)由用于存储内存位置信息的第一指针域(111)和用于存储当前 记录槽(11)使用状态信息的第一状态域(11 组成,所述扩展槽(1 由用于存储下一个 数组单元(1)位置信息的第二指针域(121)和用于存储当前数组单元(1)中记录槽(11) 的使用状态信息和当前数组单元(1)的扩展状态信息的第二状态域(12 组成,所述第一 状态域(112)的状态包括已使用和未使用两种状态,所述第二状态域(122)的状态包括记 录槽(11)为空、记录槽(11)已满和数组单元(1)已扩展三种状态。
4.根据权利要求3所述的防止内存泄露和内存多次释放的内核模块内存管理方法, 其特征在于所述步骤幻中添加内存分配记录时,首先读取第一个数组单元(1)的扩展槽 (12)的第二状态域(12 ;然后针对第二状态域(12 执行判断处理,如果当前数组单元 ⑴仍有空的记录槽(11),则将内存分配记录写入空的记录槽(11),如果数组单元⑴写入 内存分配记录后再无空的记录槽(11),则将扩展槽(1 的第二状态域(12 标记为已满; 如果当前数组单元(1)的记录槽(11)已满,则建立新的数组单元(1),将当前数组单元(1) 中扩展槽(1 的第二状态域(12 与新的数组单元(1)建立关联,然后将内存分配记录写 入新的数组单元(1)的第一个空的记录槽(11);如果当前数组单元(1)的扩展槽(12)已 经扩展出新的数组单元(1),则将下一个数组单元(1)作为当前的数组单元(1),返回上述 针对第二状态域(12 执行判断处理。
5.根据权利要求3所述的防止内存泄露和内存多次释放的内核模块内存管理方法,其 特征在于所述步骤幻中在执行内存释放时,首先在记录数组的所有数组单元(1)查找与 待释放内容相关联的内存分配记录,然后根据查找到内存分配记录对应记录槽(11)的第 一状态域(11 执行判断处理,如果第一状态域(11 为已使用状态,则终止查询与待释放 内容相关联的内存分配记录;如果第一状态域(112)为未使用状态,则继续查找与待释放 内容相关联的内存分配记录,如果找到则继续返回上述针对第一状态域(11 执行判断处 理,否则终止查询与待释放内容相关联的内存分配记录。
6.根据权利要求3或4或5所述的防止内存泄露和内存多次释放的内核模块内存管理 方法,其特征在于所述步骤幻中删除内存分配记录是指将该内存分配记录标记为未使用 状态,所述查找内存分配记录时,如果找到内存分配记录且该内存分配记录已经被标记为 未使用状态,则输出发生多次内存释放的报警信息;所述步骤4)中,如果扫描记录数组时 记录数组中仍留有内存分配记录,则输出发生内存泄露的报警信息。
全文摘要
一种防止内存泄露和内存多次释放的内核模块内存管理方法,其实施步骤如下1)建立记录数组;2)当内核模块请求系统分配内存时,向记录数组中添加与分配内存相关联的内存分配记录;3)当内核模块请求系统释放内存时,在记录数组中查找与待释放内存相关联的内存分配记录,如果存在关联的内存分配记录则执行内存释放、并删除该内存分配记录;如果不存在关联的内存分配记录则发出“多次释放”的告警;4)当内核模块退出时,扫描记录数组,如果记录数组中仍留有内存分配记录,则根据内存分配记录将其关联的内存进行逐一释放,并最终清除记录数组。本发明可防止内核模块发生内存泄露和多次内存释放,具有内存定位能力好、操作系统忙闲程度低、占用资源少、内存足迹小、适应性好的优点。
文档编号G06F12/02GK102103541SQ201110047800
公开日2011年6月22日 申请日期2011年2月28日 优先权日2011年2月28日
发明者刘晓建, 吴庆波, 孔金珠, 戴华东, 秦莹, 董攀, 颜跃进 申请人:中国人民解放军国防科学技术大学