UCOS -III 中 内存管理代码分析 (1)OSMemCreat

 

       UCOS-III也使用过一段时间了,但也只是使用而已,并没有细究代码如何实现的,有时突然喜欢个刨根问底,看下所谓的内存管理到底是个什么东东,我看源代码特别是这种操作系统的源代码,总想看到不错的代码以后为自己所用,所以留下此文当作笔记。

 

先把代码贴进来  ,我们先来看下参数。

UCOS-III 内存管理一般是一段连续的地址(因为没有虚拟内存管理,应该在物理上也是连续的),并且起始的地址必须是对齐的即是4的倍数,每块内存大小字节数也必须是4的倍数,最小要大于4个字节。内存是你起先定义好的全局数组,也就是说内存已经被申请了,这些函数是帮助你管理这些内存,方便释放和申请,这块内存被。

 

p_mem 是指向内存管理结构体的指针,里面保存了管理内存的一些指针和变量(主要是内存块数目(可供使用的内存块数目),内存地址等)。

p_name 是给你创建的内存区域起名字,方便调试 ,字符指针。注意传进去的指针指向的地址应该是全局的,不可消失的。

p_addr 你全局变量数组的起始地址

n_blks 把全局变量的数组分成多少份

blk_size 每份的大小,字节单位。

 

总的来说,例如你事先申请个char [1024]的全局数组,然后你可以分成4份,每份大小256字节 n_blk = 4,blk_size =256;

这样你每次能申请的内存就是这4块区域的其中一块,最大使用的内存要小于256,为啥要小于256,因为有些地方保存了东西帮你维护内存,当然要占用空间了。

 

/*
************************************************************************************************************************
*                                               CREATE A MEMORY PARTITION
*
* Description : Create a fixed-sized memory partition that will be managed by uC/OS-III.
*
* Arguments   : p_mem    is a pointer to a memory partition control block which is allocated in user memory space.
*
*               p_name   is a pointer to an ASCII string to provide a name to the memory partition.
*
*               p_addr   is the starting address of the memory partition
*
*               n_blks   is the number of memory blocks to create from the partition.
*
*               blk_size is the size (in bytes) of each block in the memory partition.
*
* Returns    : none
************************************************************************************************************************
*/

void  OSMemCreate (OS_MEM       *p_mem,
                   CPU_CHAR     *p_name,
                   void         *p_addr,
                   OS_MEM_QTY    n_blks,
                   OS_MEM_SIZE   blk_size,
                   OS_ERR       *p_err)
{
#if OS_CFG_ARG_CHK_EN > 0u
    CPU_DATA       align_msk;
#endif
    OS_MEM_QTY     i;
    OS_MEM_QTY     loops;
    CPU_INT08U    *p_blk;
    void         **p_link;
    CPU_SR_ALLOC();

//从这开始,主要是些检测参数的一些代码,和申请内存关系不大

#ifdef OS_SAFETY_CRITICAL
    if (p_err == (OS_ERR *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    if (OSSafetyCriticalStartFlag == DEF_TRUE) {
       *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
        return;
    }
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
    if (OSIntNestingCtr > (OS_NESTING_CTR)0) {              /* Not allowed to call from an ISR                        */
       *p_err = OS_ERR_MEM_CREATE_ISR;
        return;
    }
#endif

#if OS_CFG_ARG_CHK_EN > 0u
    if (p_addr == (void *)0) {                              /* Must pass a valid address for the memory part.         */
       *p_err   = OS_ERR_MEM_INVALID_P_ADDR;
        return;
    }
    if (n_blks < (OS_MEM_QTY)2) {                           /* Must have at least 2 blocks per partition              */
       *p_err = OS_ERR_MEM_INVALID_BLKS;
        return;
    }
    if (blk_size < sizeof(void *)) {                        /* Must contain space for at least a pointer              */
       *p_err = OS_ERR_MEM_INVALID_SIZE;
        return;
    }
    align_msk = sizeof(void *) - 1u;
    if (align_msk > 0) {
        if (((CPU_ADDR)p_addr & align_msk) != 0u){          /* Must be pointer size aligned                           */
           *p_err = OS_ERR_MEM_INVALID_P_ADDR;
            return;
        }
        if ((blk_size & align_msk) != 0u) {                 /* Block size must be a multiple address size             */
           *p_err = OS_ERR_MEM_INVALID_SIZE;
            return;
        }
    }
#endif

    //好了核心代码到了
    //首先把p_addr指针转化为(void*)型指针的指针, p_link = (void **)p_addr;为啥要这么做,其实这些内存的连接靠的是指针,每块内存区域的开头保存了指向下一个
    //内存的地址,*p_link 操作其实

    p_link = (void **)p_addr;                               /* Create linked list of free memory blocks               */
    
    //把void型指针转化为unsigned char型指针,方便后面的一个字节的移位

    p_blk  = (CPU_INT08U *)p_addr;
    
    loops  = n_blks - 1u;
    for (i = 0u; i < loops; i++) {
        p_blk +=  blk_size;
        //修改*p_link的内容, p_link的内容是什么
       //*p_link 的内容和*p_addr的一样,不同点是*p_link的内容还可以作为指针使用,
       //*p_addr 内容就是数据,即全局数组的前部分的值,首先p_blk是cahr型指针,*p_blk只能取一个字节
       // 
       *p_link = (void  *)p_blk;                            /* Save pointer to NEXT block in CURRENT block            */

       p_link = (void **)(void *)p_blk;                    /* Position     to NEXT block                             */
    }
   *p_link             = (void *)0;                         /* Last memory block points to NULL                       */

    OS_CRITICAL_ENTER();
    p_mem->Type        = OS_OBJ_TYPE_MEM;                   /* Set the type of object                                 */
    p_mem->NamePtr     = p_name;                            /* Save name of memory partition                          */
    p_mem->AddrPtr     = p_addr;                            /* Store start address of memory partition                */
    p_mem->FreeListPtr = p_addr;                            /* Initialize pointer to pool of free blocks              */
    p_mem->NbrFree     = n_blks;                            /* Store number of free blocks in MCB                     */
    p_mem->NbrMax      = n_blks;
    p_mem->BlkSize     = blk_size;                          /* Store block size of each memory blocks                 */

#if OS_CFG_DBG_EN > 0u
    OS_MemDbgListAdd(p_mem);
#endif

    OSMemQty++;

    OS_CRITICAL_EXIT_NO_SCHED();
   *p_err = OS_ERR_NONE;
}

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值