uCOS内存管理相关函数理解

内存池控制块

struct  os_mem {   

    OS_OBJ_TYPE  Type;   /* Should be set to OS_OBJ_TYPE_MEM */

    void   *AddrPtr;  //内存池的起始位置 

    CPU_CHAR      *NamePtr;  //内存池名称

    void     *FreeListPtr;   //指向空闲内存块列表(列表中第一个内存块)

    OS_MEM_SIZE    BlkSize;  //每个内存块的大小

    OS_MEM_QTY    NbrMax;  //内存块的总数量

    OS_MEM_QTY    NbrFree;   //空闲内存块数量

    OS_MEM     *DbgPrevPtr;  //指向调试列表中上一个内存池

    OS_MEM     *DbgNextPtr;  //指向调试列表中下一个内存池

    CPU_INT32U    MemID;  //第三方调试器和跟踪程序的唯一ID 

};

内存管理函数:因为内存管理是通过内存池控制块来进行的,所以和任务操作任务控制块一样,内存管理相关函数也是通过操作内存池控制块的元素值实现相应的功能。

{

OSMemCreate:内存池创建函数

{

函数思想:两件事:一是初始化内存池控制块,给其元素赋初值。二是给内存池分块,并将内存块串成单向列表。

6个入口参数:指向内存池控制块的指针p_mem;内存池名称p_name;内存池开始地址p_addr;内存块的数量n_blks;单个内存块大小blk_size(以字节为单位);返回的错误类型p_err。

函数过程:① 首先进行安全检查,中断中非法调用检查,参数检查。参数检查中,内存块的数量n_blks至少有两块;内存块的大小blk_size至少有四个字节;相当于一个内存块至少有两个字节。这里要求内存池的首地址按四字节对齐,即首地址必须是4的倍数。这一点很好判断,直接让首地址与0x03相与即可,如果为0,则表示对齐。因为二进制数除了最低两位:一个表示1,一个表示2,其余高位都是4的倍数,所以只要地址从高到低的最后两位是0,则和起来的十进制数必是4的倍数。那么通过二进制形式的按位相与(~)计算即可判断是否对齐。还要判断内存块大小blk_size是否是4的倍数,用相同方法判断即可,因为uCOS设定是内存块大小必须能够容纳整数个指针,32位系统指针大小是4个字节。② 首先,将内存块连成链表。创建链表是很简单的事:内存池的开始地址p_addr也是第一个内存块的地址,而且最开始数组元素的地址是连续的;然后进入for循环,让前一个内存块指向后一个内存块,最后一个内存块指向NULL。for循环的循环次数就是内存块数量n_blks减1(举例:3个结点连成单链表,只需要两根连线)。③ 初始化内存池控制块的元素。包括内存池起始位置,空闲内存块的地址,最大内存块个数,空闲内存块个数,内存块大小。④ 如果使能了调试列表,调用OS_MemDbgListAdd()将该内存池加入到调试列表中。统计内存池个数的全局变量OSMemQty加1,最后返回无错误类型。

}

OSMemGet()内存申请函数 

{

函数思想:只能申请一个内存块,申请多少块就调用多少次。如果还有可用的内存块,则返回对应的内存地址;没有就返回NULL。

2个入口参数:内存池控制块指针p_mem;返回的错误类型p_err。

返回:该函数是指针函数类型,返回指针void *。如果没错误,就返回指向申请的内存块的指针;有错误,返回NULL。

函数过程:① 进行安全。参数检查。② 申请内存块,当然是要判断内存池中是否有空闲的内存块。内存池控制块中的元素NbrFree表示空闲内存块数量。如果无空闲内存块(为0),那就返回错误类型为“OS_ERR_MEM_NO_FREE_BLKS”,并且return (void *)0。③ 如果有空闲内存块,那就获取当前空闲内存块的地址(内存池控制块元素FreeListPtr);然后更新空闲内存块,即让FreeListPtr指向下一个空闲的内存块,即p_mem->FreeListPtr = *(void **)p_blk。可用内存块数量NbrFree减1,返回无错误和申请到的内存块地址。

}

OSMemPut:内存释放函数

{

函数思想:内存块使用完,需要即使释放,以供其他使用。释放内存块就是将内存块重新插到内存池的空闲列表中。发现没有,内存申请函数是根据内存池空闲列表FreeListPtr一个一个获取,是从头申请,最后一个内存块指向NULL。所以内存释放函数,释放的内存块也应该插入到内存池空闲列表头部。

3个入口参数:内存池指针p_mem;将要释放的内存块指针p_blk;返回的错误类型p_err。

函数过程:① 进行安全检查,参数检查。② uCOS的释放函数感觉都是不限次数调用,首先判断可用内存块个数NbrFree是否大于内存池最多内存块数NbrMax,如果大于等于,意味着所有的内存块都已经被释放,不需要进行后面的步骤,直接返回相应的错误类型和return即可。③ 如果确实有没释放的内存块,就将它插入到内存池空闲列表的头部。这只需要修改FreeListPtr指针,改为指向该释放内存块;然后将该释放内存块指向FreeListPtr刚开始指向的内存块。然后更新可用内存块个数:NbrFree加1;UI后返回无错误。

}

}

猜你喜欢

转载自blog.csdn.net/m0_43443861/article/details/126442364