发明内容
本发明针对以上的弊端,采用内存池的设计,对内存的分配与释放进行集中管理,代替直接调用malloc/free、new/delete进行内存管理的常用方法。
为实现该目的,本发明采用如下技术方案:
一种用于流媒体服务器的内存集中动态分配方法,对不同的数据类型进行内存分配时,集中动态管理分配和释放,实现方式如下,
步骤S1,内存初始化时,传入的参数包括内存块单元大小和内存块单元数量;
步骤S2,对申请的内存块单元大小进行4位字节对齐运算;
步骤S3,通过冒泡法对申请的各内存块单元相应内存块单元大小进行从小到大的排序,得到相应数组;对应的内存块单元数量也对应排序,得到相应数组;
步骤S4,根据步骤S3所得申请的内存块单元大小相应数组和内存块单元数量相应数组,将内存块单元大小相同的内存块单元进行合并,每种内存块单元大小对应一种内存块类型,得到内存块类型分别相应单元块数量;
步骤S5,分配内存池地址,初始化内存池,创建内存池互斥对象;根据步骤S4所得结果,遍历各内存块类型,配置内存块信息,针对当前内存块类型根据相应单元块数量遍历生成空闲内存块单元节点链表;
步骤S6,根据需要,将已分配的内存池空闲空间分配给新节点,释放掉不需要的内存节点。
而且,步骤S5中,遍历各内存块类型时,配置内存块信息如下,
赋值内存块空间TBlockInfo的地址为内存池指向的内存空间地址加上当前i值;
初始化内存块空间大小赋值为内存块单元大小数组标号为i对应元素的值A(i);
初始化内存块空间单元个数为内存块单元数量数组标号为i对应元素的值B(i);
初始化可用单元为零,初始化已用单元个数为零;
初始化内存块空间开始地址为,分配大小为A(i)×B(i)的内存空间指向的地址;
赋值内存块空间的结束地址为,内存块空间开始地址加上A(i)×B(i)。
而且,步骤S6中,将已分配的内存池空闲空间分配给新节点实现方式为,
导入需要分配的内存块单元,锁定内存池互斥变量;以内存块的类型BlockType数值为变量循环遍历内存池;比较需要分配内存块单元大小与内存池中空闲内存块单元的内存块单元大小比较,如果为真,从空闲内存块单元中取出第一个大于需要分配内存块单元的内存块单元,将内存块单元从空闲单元链表中取出,插入到已用的内存块链表中,同时将对应的可用的内存块数目减1以及已用的内存块数目加1。
而且,步骤S6中,释放掉不需要的内存节点实现方式为,
导入需释放的内存节点,从内存池中找到该节点,并从已用的内存块链表中删掉,然后插入到可用的内存块链表中,同时将对应的可用的内存块数目加1以及已用的内存块数目减1。
本发明通过采用内存池的设计,对内存的分配与释放进行集中管理,代替直接调用malloc/free、new/delete进行内存管理的常用方法,避免频繁使用malloc/free、new/delete,带来的用比较多的系统资源问题,提高了程序和系统的运行效率,避免产生大量的内存碎片以及内存泄露带来的问题,具有重要的市场价值。
实施例提供的一种用于流媒体服务器的内存集中动态分配方法,包括以下步骤:
(一)S1:内存初始化时,向初始化内存函数传入内存块单元大小(BlockSize),内存块单元数量(BlockNum),流程转向S201;例如函数参数为(内存块单元大小为数组[8,24,308],内存块单元数量值为数组[1000,1000,1000])。
初始化内存信息结构体,具体可包含如下变量:内存块单元大小(BlockSize),内存块单元数目(BlockNum),已用的内存块数目(UsedNum),可用的内存块数目(FreeNum),内存开始位置(StartAddress),内存结束位置(EndAddress),已用的内存块(UsedBlock),可用的内存块(FreeBlock);输入初始化函数参数,依次为内存块单元大小(BlockSize),内存块单元数量(BlockNum),内存块单元的类型(BlockType);内存块单元大小(BlockSize)为整型数组,数组的值为需要存储的单个结构体的大小;内存块单元数量为对应的结构体的数据单元数量;内存块单元的类型为定义的类型值,例如内存块单元大小8,24,308分别对应类型0,1,2;
(二)S2:对申请的内存块单元大小(BlockSize)进行4位字节对齐运算,其优点为:CPU在读取内存数据的时候4字节对齐会取得更快的速度;这是因为:1字节8位,4字节正好32位,而32位机器的寄存器,地址都是32位的,正好一次处理就完成,速度更快;实施例具体实现为以下子步骤:
S201:如果内存块单元(BlockSize)和0x03进行与运算为true,流程转向S203;如果内存块单元(BlockSize)和0x03进行与运算为false,流程转向S202;
S202:内存块单元大小(BlockSize)重新赋值为原内存块单元大小加上4,流程转向S301;
S203:内存块单元大小(BlockSize)重新赋值为4减去与运算的结果再加上原内存块单元大小;流程转向S301;(比如:内存块单元大小为数组[8,24,308],经过4位字节变换以后:内存块单元大小为数组[12,28,312])
(三)S3:对申请的内存块单元大小(BlockSize)进行排序,得到相应数组:
S301:通过冒泡法对申请的各内存块单元相应内存块单元大小进行从小到大的排序,对应的内存块单元数量(BlockNum)也对应排序;流程转向S401;(比如:内存块单元大小为数组[24,8,308],内存块单元数量值为数组[1000,2000,3000],经过排序后为:内存块单元大小为数组[8,24,308],内存块单元数量值为数组[2000,1000,3000])
冒泡排序实现方式为:比较相邻的元素。如果第一个比第二个大,就交换他们两个,对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。针对所有的元素重复以上的步骤,除了最后一个。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
(四)S4:根据S3所得申请的内存块单元大小(BlockSize)相应数组,将内存块单元大小相同的内存块单元进行合并,每种内存块单元大小对应一种内存块类型,得到内存块类型分别相应单元块数量:
S401:比较内存块单元的大小,如果内存块单元大小相同,则合并,即内存块大小(BlockSize)相同的数量相加,更新相应内存块单元数量(BlockNum),如果不相同则跳过;流程转向S501;(比如:内存块单元大小为数组[8,8,308],内存块单元数量值为数组[1000,2000,3000],经过合并后为:内存块单元大小为数组[8,308],内存块单元数量值为数组[3000,3000],则内存块类型0相应单元块数量为3000,内存块类型2相应单元块数量为3000)。
(五)S5:采用链表的方式初始化内存池;通过malloc分配内存池的空间,创建内存池的互斥锁(Mutex),赋值内存池的内存类型;分配内存块空间,并初始化内存块空间数据值为零。实施例根据S4所得结果,分配一组按照从小到大排列的内存块单元模块数组,具体实现如下:
S501:分配内存池地址,初始化内存池,创建内存池互斥对象:分配内存池地址;创建内存池互斥锁,分配数量为内存块单元数组长度的内存块空间(TBlockInfo)(如:ptBlockInfo=(TBlockInfo*)malloc(3*sizeof(TBlockInfo))),并赋值内存池指向的内存空间地址为内存块空间(如:ptMemPool->ptBlockInfo=ptBlockInfo),以实现对每个类型进行空间分配,
ptBlockInfo、ptMemPool是自定义的结构体;流程转向S502;
sizeof:是C的标准库函数,是C/C++中的一个操作符;
*:是C语言中,标识指针类型的符号;
->:在C语言中,它是用于指向结构体的运算符。
S502:开始分配内存池内存块单元空间,为循环遍历内存块类型,首先令计数器i=0:自变量i为内存块类型,取值范围为0到(内存块类型总数-1),以便循环遍历内存块类型,所述内存块类型总数是总类型的个数,指不同的内存块的种类数量;流程转向S503;
S503:根据当前的内存块类型i,配置内存块信息(内存块大小,内存块数量,内存块可用数量,内存块已用数量,内存块开始地址),流程转向S504;
具体配置如下:
赋值内存块空间(TBlockInfo)的地址为内存池指向的内存空间地址加上当前i值;
初始化内存块空间大小赋值为内存块单元大小数组标号为i对应元素的值A(i);
初始化内存块空间单元个数为内存块单元数量数组标号为i对应元素的值B(i);
初始化可用单元为零,初始化已用单元个数为零;
初始化内存块空间开始地址为,分配大小为A(i)×B(i)的内存空间指向的地址;
赋值内存块空间的结束地址为,内存块空间开始地址加上A(i)×B(i);
S504:开始循环遍历单元块数量,初始化计数器j=0:自变量j为当前类型中单元块标识,取值范围为0到(当前类型i相应内存块单元数量-1);流程转向505;
S505:根据当前的单元块j,生成空闲内存块单元节点链表:生成空闲节点链表,申请一个局部内存块单元结构空间,赋值内存块单元为零;单元内存地址赋值为内存信息开始地址加上已循环的单元数;将内存块单元节点插入到可用的内存块(FreeBlock)节点链表第一个位置,且可用的内存块数目(FreeNum)加1,计数j加1(j++),即j=j+1;流程转向S506;
S506:判断计数器j是否小于(当前类型i相应内存块单元数量-1);如果判断结果为true,流程转向S505,继续配置当前类型i的下一个内存块单元;如果判断结果为false,说明当前类型i的内存块单元已经配置完毕,流程转向S507;
S507:计数器i加1,即令计数器i++,即i=i+1;流程转向S508;
S508:判断计数器i是否小于(内存类型总数-1),如果计算结果为true,流程转向S503,继续配置下一类型的内存块单元;如果计算结果为false,配置完成,流程转向S601;
(六)S6:根据需要分配内存块和释放内存块,包括将已分配的内存池空闲空间分配给新节点,释放掉不需要的内存节点:
S601:导入需要分配的内存块单元,锁定内存池互斥变量;以内存块的类型(BlockType)数值为变量循环遍历内存池;比较需要分配内存块单元大小与内存池中空闲内存块单元的内存块单元大小比较,如果为真,即从空闲内存块单元中取出第一个大于需要分配内存块单元的内存块单元,将内存块单元从空闲单元链表中取出,插入到已用的内存块(UsedBlock)链表中,同时将对应的可用的内存块数目(FreeNum)减1以及已用的内存块数目(UsedNum)加1;循环break;
S602:导入需释放的内存节点,从内存池中找到该节点,并从已用的内存块(UsedBlock)链表中删掉,然后插入到可用的内存块链表(FreeBlock)中,同时将对应的可用的内存块数目(FreeNum)加1以及已用的内存块数目(UsedNum)减1。
本文中所描述的具体实施例仅仅是对本发明的举例说明。本发明所属技术领域的技术人员可以对所描述的具体实例做各种各样的修改或补充或采用类似的方式替代,但并不会偏离本发明的精神或者超越所附权利要求书所定义的范围。