Ucos源码分析------内存管理

Ucos源码分析

1.Ucos源码分析------任务控制块与任务调度
2.Ucos源码分析------事件控制块与事件控制
3.Ucos源码分析------信号量
4.Ucos源码分析------邮箱与队列
5.Ucos源码分析------事件标志组
6.Ucos源码分析------内存管理
7.Ucos源码分析------临界区与中断管理
8.Ucos源码分析------OS启动
9.Ucos总结


内存管理----OS_MEM.C

  • Ucos源码分析
  • 1.内存分区与内存块
  • 2.内存块的创建
  • 3.内存块的获取
  • 4.内存块的释放


1.内存分区与内存块

应使用动态内存,要首先在内存中划分出可以进行动态分配的区域,这个划分出来区域叫做内存分区,每个分区要包含若干个内存块。μC/OS-II要求同一个分区中的内存块的字节数必须相等,而且每个分区与该分区的内存块的数据类型必须相同。

实现方式:定义一个二维数组
INT8U IntMenBuf[10][4]来存储INT8U类型的数据,10个内存块。每个内存块长度为4字节(8位)的数据。

内存控制块

控制块成员
OSMemAddr 内存分区的指针
OSMemFreeList 内存控制块链表指针 或 当前空闲的内存块指针
OSMemBlkSize 分区内 内存块长度
OSMemNBlks 分区内 内存块数目
OSMemNFree 分区内 当前可分配的内存块数目

2.内存块的创建

OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
参数:
  addr 建立的内存区的起始地址。可以使用静态数组或在初始化时使用 malloc()函数建立。
  Nblks 需要的内存块的数目。每一个内存区最少需要定义两个内存块。
  Blksize 每个内存块的大小,最少应该能够容纳一个指针。
  Err 是指向包含错误码的变量的指针。

OS_MEM  *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr;
#endif    
    OS_MEM    *pmem;
    //内存块指向用
    INT8U     *pblk;
    void     **plink;
    INT32U     i;

   OS_ENTER_CRITICAL();
    // 获取空闲内存控制块
    pmem = OSMemFreeList;                             /* Get next free memory partition                */
    // 判断空闲内存控制块链表是否满
    if (OSMemFreeList != (OS_MEM *)0) {               /* See if pool of free partitions was empty      */
        // 空闲内存控制块未满,移动到下一个空闲内存控制块
        OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
    }
    OS_EXIT_CRITICAL();
    if (pmem == (OS_MEM *)0) {                        /* See if we have a memory partition             */
        *err = OS_MEM_INVALID_PART;
        return ((OS_MEM *)0);
    }
    //将下一个内存块的地址 放在当前内存块的第一个位置
    plink = (void **)addr;                            /* Create linked list of free memory blocks      */
    pblk  = (INT8U *)addr + blksize;
    //遍历内存块数目
    for (i = 0; i < (nblks - 1); i++) {
        //当前位置 的内容放下一个内存块的地址
        *plink = (void *)pblk;
        ///plink指向 下一个内存块的地址
        plink  = (void **)pblk;
        //pblk 获取下一内存块地址
        pblk   = pblk + blksize;
    }
    //最后一个内存块指向空
    *plink              = (void *)0;                  /* Last memory block points to NULL              */
    //内存控制块初始化
    pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
    pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
    pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
    pmem->OSMemNBlks    = nblks;
    pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
    *err                = OS_NO_ERR;
    return (pmem);
}

Ucos源码分析------内存管理_第1张图片

3.内存块的获取

void *OSMemGet (OS_MEM *pmem, INT8U *err)
参数:
  pmem 是指向内存区控制块的指针
  Err 是指向包含错误码的变量的指针

void  *OSMemGet (OS_MEM *pmem, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr;
#endif    
    void      *pblk;

    OS_ENTER_CRITICAL();
    // 如果还有内存块
    if (pmem->OSMemNFree > 0) {                       /* See if there are any free memory blocks       */
        //获取内存块的地址
        pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
        //下一个内存块的地址 放在当前内存块的第一个位置[0]
        pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
        //内存块数目减少
        pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;                             /*      No error                                 */
        return (pblk);                                /*      Return memory block to caller            */
    }
    OS_EXIT_CRITICAL();
    *err = OS_MEM_NO_FREE_BLKS;                       /* No,  Notify caller of empty memory partition  */
    return ((void *)0);                               /*      Return NULL pointer to caller            */
}

4.内存块的释放

INT8U OSMemPut (OS_MEM *pmem, void *pblk)
参数:
  pmem 是指向内存区控制块的指针
  Pblk 是指向将被释放的内存块的指针

INT8U  OSMemPut (OS_MEM  *pmem, void *pblk)
{
//进入临界区的方式
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif    

    OS_ENTER_CRITICAL();
    //判断内存块是不是满的
    if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
        OS_EXIT_CRITICAL();
        return (OS_MEM_FULL);
    }
    // 将当前内存块的位置 放在新加入的内存块的第一个位置[0]
    *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
    //内存控制块的 当前内存块链表 指向新加入的内存块
    pmem->OSMemFreeList = pblk;
    //内存块数目+1
    pmem->OSMemNFree++;                          /* One more memory block in this partition            */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);                          /* Notify caller that memory block was released       */
}

经过多次OSMemPut()和OSMemGet()后,内存分区中内存块的指向,变的随意。

你可能感兴趣的:(RTOS,mcu)