信号处理算法中的动态内存处理操作的方法及装置的制作方法

文档序号:6463389阅读:217来源:国知局
专利名称:信号处理算法中的动态内存处理操作的方法及装置的制作方法
技术领域
本发明属于数字信号处理领域,特别涉及信号处理算法中的动态内存处理 操作的方法及装置。
背景技术
数字信号处理算法的核心实现代码中经常包含动态内存的分配和释放操作,这些操作在参考代码中一般用c的标准库函数实现,常用的库函数有malloc(), calloc(), free()和alloca()。高效,安全,灵活的在嵌入式平台上实现 动态内存的分配和释放,是这些算法成功的移植到这些平台的前提。直接使用C标准库函数,由相应的C编译器负责它们的具体操作是最简 单,最直接的实现方式,但是多数嵌入式处理器的C编译器都不支持alloca(), 且手工实现与C标准库函数完全兼容的alloca()有相当的复杂度。此外出于成 本和系统复杂度的考虑,嵌入式系统中可能没有具备内存管理能力的操作系 统,而是根据自身系统的特点以一种特定方式实现了简单的malloc()和free() 函数。虽然可以基于malloc()实现其它内存分配函数,但在数字信号处理算法 的核心代码中包含内存分配和释放操作是不符合算法代码移植到嵌入式系统 的一般实现原则(即TIXDAIS标准)的。这种实现机制主要的缺点如下可靠性差系统没有实现对内存操作的严格控制,无法知道算法的核心实 现代码在实际运行中究竟4吏用了多少堆栈空间,是否有足够多的资源满足动态 内存的需求。如果算法核心代码中存在内存泄漏,或者需要的堆栈空间超过可 用系统资源,出现内存操作失败或错误,会导致运算结果4晉误,系统崩溃等严 重后果。发明内容为了解决现有技术中动态内存分配和释放操作不符合TI XDAIS标准使得 可靠性差的问题,本发明实施例提供了信号处理算法中的动态内存处理操作的 方法,应用于嵌入式平台上,包括数字信号处理算法的外部主程序申请两块固定位置和尺寸的内存空间作 为堆空间和栈空间;执行数字信号处理算法的核心实现代码时,在所述堆空间和栈空间内进行 内存处理操作。同时本发明实施例还提供一种信号处理算法中的动态内存处理操作的方 法及装置,应用于嵌入式平台上,包括申请模块用于数字信号处理算法的外部主程序申请两块固定位置和尺寸 的内存空间作为堆空间和栈空间;处理模块用于执行数字信号处理算法的核心实现代码时,在所述堆空间 和栈空间内进行内存处理操作。由上述本发明提供的具体实施方案可以看出, 正是由于执行数字信号处理算法的核心实现代码时,在主程序申请的固定位置 和尺寸的堆空间和栈空间内进行内存处理操作,使得本方案具有很好的可靠 性。


图1为本发明提供的第一实施例方法流程图; 图2为本发明提供的第二实施例系统结构图。
具体实施方式
本发明公开的信号处理算法中的动态内存处理操作的方法应用于嵌入式 平台上,其基本思想是数字信号处理算法的核心实现代码中不包含任何真实的内存分配和释放操作,由调用算法核心实现代码的外部主程序提供大小固定的 两块分别作为堆空间和栈空间的可用内存空间。执行核心实现代码时,在主程 序申请的堆空间和栈空间内进行内存处理操作。核心实现代码中用到的动态内 存均取自这两块内存空间,不直接进行系统内存分配和释放操作。算法核心代 码将这两块空间的首地址指针和尺寸存于特定的非静态堆、栈信息数据结构体 中。核心代码中釆用前、后向移动数据地址指针和增、减内存使用量计数器的方式来模拟内存的分配和释放。这种实现方法符合TIXDAIS标准,明确了算 法的资源需求。因此算法的实现代码具有很好的可靠性。进一 步检测内存空间的使用量。 一旦出现内存需求量超出实际拥有量的情 况,停止内存分配,退出算法核心代码的执行或开始新的执行周期。本发明根 据内存空间的生命周期来区分堆空间和栈空间。堆空间中存放的各种数据占用 固定尺寸,固定位置的内存空间,算法核心代码的执行过程中不对堆空间中的 数据进行释放和搬移操作;栈空间的释放采取恢复栈信息结构体数据来完成, 且根据函数本身的执行过程和调用情况采用不同的实现方式,极大的减少了实 现复杂度。本发明的这种实现机制符合TIXDAIS标准,具有可靠性高,移植性好, 可重入性好,复杂度低的特点。本发明提供的第一实施例是信号处理算法中的动态内存处理操作的方法, 图1是本发明提出的实施方案流程框图,其中虚线框中的操作由算法代码完成, 这里认为算法C代码以API的形式被外部主程序调用。(注本发明的核心是 一种实现机制,图中给出的框图只;l^一个解释性的作用。本发明以OggVorbis 解码器在ARM平台上的移植为例)首先统计出算法核心代码在执行过程中需要的堆,栈空间尺寸,主程序据 此申请两块固定尺寸的内存空间,分别作为堆空间和栈空间,算法代码中的堆, 栈空间均在这两块内存空间中分配得到。而后初始化堆,栈数据结构,记录这 两块内存空间的首地址和尺寸。执行算法核心代码时,根据需求进行堆/栈空间的分配和栈空间的释力文。分配其实是在堆空间或栈空间中划定一块空闲区域, 指定某个数据项使用该块区域,也即指定数据项的存放空间的起始地址和终止 地址。各数据项的终止地址即是下一个数据项的起始地址。释放即是通知程序 其它数据项可以存放在这块内存空间中。通过内存空间使用量计数器监测内存 空间供需关系,如出现堆空间不够用的情况,停止算法代码的执行,回到主程 序并释放申请的两块内存空间,结束主程序的运行。如出现栈空间不够用的情 况,释放所有分配的栈空间,终止算法代码的本次执行周期,启动新的执行周 期。算法代码执行完毕后,由主程序释放申请的两块内存空间后,结束主程序的运行。方法流程如图l所示,包括 步骤10h统计堆/栈空间需求。本发明提出的方案符合TI XDAIS标准,即由主程序分配两块固定尺寸的 内存空间,分别作为堆,栈空间,数字信号处理算法的核心实现代码中的内存 空间都在这两块空间中分配得到,不直接从系统获取动态内存。因此需要统计 核心实现代码的堆,栈空间需求量。首先考察参考代码,区分数据内存分配应在两块内存空间中的哪块中进 行。认为使用alloca()分配得到的内存应在栈空间中获得。对于使用malloc()和 calloc()分配得到的内存,如果是算法的工作空间,在多个函数和处理模块中使 用,且尺寸相对固定,则认为在堆空间获得。如果它们只是在某个函数的处理 过程中申请的的临时空间,在这个函数退出时即行释放,认为此类临时内存空 间应在栈空间中获得。这样划分堆,栈空间的目的是在核心实现代码的执行过 程中,只进行栈空间的释放操作,不进行堆空间的释放才喿作,从而大幅降低内 存操作函数的复杂度。完成数据项分配空间的划分后,需要统计两块空间总的需求量。动态内存 的分配具有尺寸随需而定的特点,核心实现代码的每次执行过程中需要的动态 内存尺寸会不同。例如Ogg Vorbis解码器在解不同版本的编码器编出的码流时, 需要的堆,栈空间尺寸相别很大。 一种方法是考察算法的执行过程,确定某数据项可能的最大内存需求。以解码器中经常存在的内存分配操作为例/*memory allocation */ intn = readbits(10); int *pl= (int *)malloc(sizeof(int)*n); 上述伪码中,readbits(n)表示从码流中读取n bits的操作。 对于ARM系统, 一个int型数据字长为4Bytes,则数据项pi的最大堆空 间需求为4kBytes。(注如无特别说明,动态内存需求量均以Bytes为单位。) 依据这种方法统计得到的动态内存需求量是理论最大值,主程序据此进行 动态内存申请,可以保证核心实现代码在任何执行过程中都不会出现内存空间 不够用的情况,但是此时得到的动态内存需求量往往是GBytes级的,不可实 现且没有必要。实用的方法是考察算法在若干次典型执行过程中的动态内存需 求量,再加上一定的放大量。例如考察OggVorbis解码器在解码若干较早版本 编码器编出的高码率流时动态内存的需求量,记录下最大值 HEAP_SIZE—MAX—R, STACK—SIZE—MAX_R,则实际的分配量为— —息OC4r五=肌CX — S/ZE _ —歸(工b)其中,i/£^P—S7Z五—^LL0C4Z&和SZ4O: — S/Z五—JZ丄OC47^分别是主程序申请的两块作为堆,栈空间的尺寸。","为比例因子,取值应综合考虑系统的内存 供需关系,典型值为1.2,即放大量为统计值的20%。这种方法可以保证绝大 多数情况下核心实现代码能得到需要的动态内存,同时主程序可以严格控制动 态内存的申请和释放,具有更高的可靠性和灵活性,算法核心代码的移植也与 各平台的具体内存操作无关。步骤102:主程序申请动态内存。主程序调用相应的系统内存管理函凄丈,申i奮两块尺寸分别为TffiAP—S/Z£_^ZOC4r£和SWCi:—SiZ£ —v4丄丄(9C4r五的内存空间heap space 和STACK_SPACE。应确保内存空间申请成功并且首地址是4字节对齐的。如果失败,应停止主程序的运行。步骤103:堆,栈空间信息结构体的定义和初始化。堆,栈空间信息结构体用来记录与内存操作相关的信息,包括两块空间的 首地址,当前可用空间的首地址和已占用内存空间的尺寸。栈空间信息结构体 定义示例如下/* Stack struct definition sample*/ typedef struct —stack—buff {unsigned char *stack_pointer_beg; unsigned char *stack_pointer_curr;int StackSizeTot; int StackSizeUsed; int OverflowFlagj} STACK—BUFF; 该结构体中各元素的意义如下stack_pointer—beg:才戋空间的首i也址。stack_pointer_curr:数据项地址指针,指示可用空间的首地址,即前一个 数据项内存空间的终止地址。StackSizeTot:主程序申请的作为栈空间的内存块尺寸。 StackSizeUsed:已使用的栈空间尺寸。OverflowFlag:栈空间溢出标志,该标志为1时,表明主程序申请的栈空 间尺寸偏小,无法满足需求。堆空间信息结构体的定义与此类似。注意信息结构体不要声明为静态全局变量,以符合TI XDAIS标准对于算法核心代码可重入性的要求。 栈空间信息结构体的初始化函数如下示例 /* STACK—BUFF Struct Initialization sample*/void Stack_init(STACK_BUFF *pStackBuf, unsigned char*pStackSpaceBegPointer,int STACK—SIZE—ALLOCATE)pStackBuf->stack_pointer—curr =pStackBuf->stack_pointer_beg = pStackSpaceBegPointer;pStackBuf->StackSizeTot = STACK—SIZE—ALLOCATE; pStackBuf->StackSizeUsed = 0;pStackBuf->OverflowFlag = 0;函数参数pStackBuf: 栈信息结构体指针。pStackSpaceBegPointer:主程序申请的对应栈空间的内存块的首地址。 STACK_SIZE—ALLOCATE: 主程序申请的对应栈空间的内存块的尺寸。堆空间信息结构体的初始化函数与此类似。 步骤104:模拟堆,栈空间的分配。这里并不进行真实意义上的从系统中申请一块空闲的内存空间,而是在主 程序获得的内存块中指定一个数据项的起始和终止地址,并确保其它数据项不 会再放入这段内存。以下是栈空间的分配函数示例/*alloca simulation*/void* ov一alloca(int size, STACK—BUFF *pStackBuf)unsigned char *tmp = pStackBuf->stack_pointer_curr; int size—needed = ((size+3)》2)《2;if(size—needed < 0||pStackBuf->OverflowFlag) return NULL;pStackBuf->StackSizeUsed += size—needed;if(pStackBuf->StackSizeUsed > pStackBuf->StackSizeTot)pStackBuf->OverflowFlag = 1 j return NULL;pStackBuf->stack_pointer_curr += size—needed; return ((void *)tmp);函数参数size :当前数据项需要的栈空间尺寸。 pStackBuf: 栈信息结构体指针。以下筒要说明第一步,緩存栈空间可用空间首地址,如果可以进行分配, 它即是分配给当前数据项的内存空间的首地址。第二步,按4字节对齐的原则 重新统计当前数据项需要的栈空间尺寸。第三步,检查是否可以进行内存分配。 第四步,更新已用栈空间尺寸计数器。第五步,4全查是否溢出。第六步,前向 移动可用空间首地址指针,表示一块尺寸为size—needed的栈空间分配给当前数据项,其它数据项应放置在其后的栈空间中。最后返回緩存的栈空间可用空 间首地址。步骤105:判断堆空间需求量是否过大。如果堆空间需求量过大分配失败,则执行步骤106,停止核心实现代码的 执行,进而执行主程序释放申请的内存空间步骤。否则执行步骤107。 步骤107:判断栈空间需求量是否过大。如栈空间分配成功,执行步骤108该函数返回该段空间的首地址;如分配 失败,执行步骤109,返回空指针,此时应该结束算法代码的本次执行,释方文 所有分配的栈空间,开始核心实现代码新的执行周期。通过4全测OverflowFlag 标志或者考察内存分配函凄史返回值,可以准确的判断内存空间分配是否失败。步骤108:栈空间的释放,执行步骤110。步骤109:释放所有栈空间启动核心实现代码新的执行周期,返回执行步 骤104。步骤110:判断核心实现代码是否结束执行。若是执行步骤111,否则返 回执行步骤104。本发明的一个实施原则是只进行栈空间的释放,不进行堆空间的释放,以 减少内存操作的复杂度。理想的栈空间释放位置在申请该栈空间的函数结束运行时。最简单的方法 是后向回退数据项地址指针stack_pointer—curr和内存使用量计算器 StackSizeUsed的值。本发明中采取恢复栈信息结构体数据的方法进行栈空间的 释放,参考代码如下/*free stack buffer by restoring stack info struct*//*back stack struct*/STACK—BUFF StackBufStructTmp =* pStackBuf;/^allocate stack space*/void * pi = ov_alloca(size, pStackBuf);/*code using pi here *//*restore stack struct */ *pStackBuf = StackBufStructTmp; /*following codes do not use pi*/第一步,緩存栈信息结构体;第二步,进行栈空间内存申请。第三步, 使用申请到的栈空间。第四步,恢复栈信息结构体。显然,栈信息的緩存应在栈空间的申请之前,栈信息结构体的恢复在不再 需要该栈空间中的数据之后。栈空间的释放根据函数本身的执行过程和调用情况采用不同的实现方式。 如果某个函数的退出接口是唯一的,则以上緩存和恢复代码应直接置于该函数 内部即由申请和使用栈空间的函数自己负责释;^史栈空间,这样即使该函数在多处被调用,也不需增加额外的控制代码。如果某函数执行流程复杂,存在多个退出接口;且函数中只进行一次栈空间申请,或者虽进行多次栈空间申请,但 没有提前释放某块栈空间,则在该函数被调用前緩存栈数据结构,调用结束后 恢复栈数据结构即由调用该函数的函数负责释放栈空间,这种实现方法可以避 免由于遗漏了某个退出接口的恢复代码而导致的内存泄漏。更复杂的情况则需 要仔细考察函数的调用和退出情况,避免内存泄漏。 步骤lll:主程序释放申请的内存空间。算法执行完毕后,由主程序调用相应的系统内存管理函数释放申请的两块 内存空间。本发明提供的第二实施例是信号处理算法中的动态内存处理操作的装置, 应用于嵌入式平台上,其结构如图2所示,包括申请4莫块201:用于数字信号处理算法的外部主程序申请两块固定位置和 尺寸的内存空间作为堆空间和栈空间;处理模块202:用于执行数字信号处理算法的核心实现代码时,在所述堆 空间和栈空间内进行内存处理操作。进一步所述处理模块202还包括处理子模块2021:用于在所述堆空间进行 堆空间分配,在所述栈空间进行栈空间的分配和释放。处理子模块2021包括堆处理子模块20211:用于堆空间中存放的各种数 据项占用固定尺寸,固定位置的内存空间;且算法核心代码的执行过程中不对堆空间中的数据项进行释放和搬移操作。处理子模块2021包括栈处理子模块20212:用于核心实现代码通过控制 数据项地址指针的移动和增减内存使用量计数器值模拟栈空间分配和释放,并 通过内存使用量计数器进行内存使用量的监测。该装置,还包括确定模块203:用于确定核心实现代码在执行过程中需要堆空间和栈空间 大小;分配模块204:用于外部主程序根据所确定的堆空间和栈空间大小进行内 存空间申请。显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发 明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及 其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。
权利要求
1. 一种数字信号处理算法中动态内存处理操作的方法,应用于嵌入式平台上,其特征在于,包括数字信号处理算法的外部主程序申请两块固定位置和尺寸的内存空间作为堆空间和栈空间;执行数字信号处理算法的核心实现代码时,在所述堆空间和栈空间内进行内存处理操作。
2、 如权利要求1所述的方法,其特征在于,所述进行内存处理操作具体 为在所迷堆空间进行堆空间分配,在所述栈空间进行栈空间的分配和释放。
3、 如权利要求2所述的方法,其特征在于,在所述堆空间进行堆空间分 配具体为堆空间中存放的各种数据项占用固定尺寸,固定位置的内存空间; 且算法核心代码的执行过程中不对堆空间中的数据项进行释放和搬移操作。
4、 如权利要求2所述的方法,其特征在于,核心实现代码通过控制数据 项地址指针的移动和增减内存使用量计数器值才莫拟栈空间分配和释放,并通过 内存使用量计数器进行内存使用量的监测。
5、 如权利要求4所述的方法,其特征在于,核心实现代码中申请栈空间 的函数结束运行时,由所述申请栈空间的函数负责释放栈空间。
6、 如权利要求4所述的方法,其特征在于,由申请和^f吏用栈空间的函数 的调用函数负责释放栈空间。
7、 如权利要求1所述的方法,其特征在于,在数字信号处理算法的外部 主程序分配固定位置和尺寸的堆空间和栈空间步骤前还包括确定核心实现代码在执行过程中需要堆空间和栈空间大小;外部主程序根据所确定的堆空间和栈空间大d 、进行内存空间分配。
8、 如权利要求7所述的方法,其特征在于,确定核心实现代码在执行过程中需要堆空间和栈空间大小具体为考察核心实现代码在典型执行过程中需要的堆空间和栈空间大小,再加上一定的放大量,最终确定核心实现代码在执行过程中需要堆空间和栈空间大 小。
9、 一种数字信号处理算法中动态内存处理操作的装置,应用于嵌入式平 台上,其特征在于,包括申请模块用于数字信号处理算法的外部主程序申请两块固定位置和尺寸 的内存空间作为堆空间和栈空间;处理模块用于执行数字信号处理算法的核心实现代码时,在所述堆空间 和栈空间内进行内存处理操作。
10、 如权利要求9所述的装置,其特征在于,所述处理模块还包括处理子 模块用于在所述堆空间进行堆空间分配,在所述栈空间进行栈空间的分配和 释放。
11、 如权利要求10所述的装置,其特征在于,所述处理子模块包括堆 处理子模块用于堆空间中存放的各种数据项占用固定尺寸,固定位置的内存 空间;且算法核心代码的执行过程中不对堆空间中的数据项进行释放和搬移操作。
12、 如权利要求10所述的装置,其特征在于,所述处理子模块包括栈 处理子模块用于核心实现代码通过控制数据项地址指针的移动和增减内存使 用量计数器值模拟栈空间分配和释放,并通过内存使用量计数器进行内存使用 量的监测。
13、 如权利要求9所述的装置,其特征在于,还包括确定模块用于确定核心实现代码在执行过程中需要堆空间和栈空间大小;分配模块用于外部主程序根据所确定的堆空间和栈空间大小进行内存空 间申请。
全文摘要
公开了一种数字信号处理算法中动态内存处理操作的方法及装置,为了解决现有技术中动态内存分配和释放操作不符合TI XDAIS标准使得可靠性差的问题,本发明公开的方法包括数字信号处理算法的外部主程序申请两块固定位置和尺寸的内存空间作为堆空间和栈空间;执行数字信号处理算法的核心实现代码时,在所述堆空间和栈空间内进行内存处理操作,正是由于执行数字信号处理算法的核心实现代码时,在主程序申请的固定位置和尺寸的堆空间和栈空间内进行内存处理操作,使得具有很好的可靠性。
文档编号G06F9/34GK101266540SQ20081010487
公开日2008年9月17日 申请日期2008年4月24日 优先权日2008年4月24日
发明者冯宇红, 昊 邓 申请人:北京中星微电子有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1