18363890557 发表于 2020-9-21 09:47:33

09-μCOS-II中内存管理程序使用说明





前言  环形队列,链表,内存管理,这些典型的数据缓存处理方式  作为一个开发者是应该掌握的知识点  由于后面的文章涉及到了内存管理  故,这节先说一下内存管理
uCOSII中的内存管理源码  我把uCOS中的内存管理程序拷贝出来了  


  OS_MEM.C/***********************************************************************************************************                                                uC/OS-II*                                          The Real-Time Kernel*                                          MEMORY MANAGEMENT**                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL*                                           All Rights Reserved**                                                V2.00** File : OS_MEM.C* By   : Jean J. Labrosse**********************************************************************************************************/
#defineOS_MEM_C_#include "OS_MEM.h"

//#if OS_MEM_EN && OS_MAX_MEM_PART >= 2/***********************************************************************************************************                                       LOCAL GLOBAL VARIABLES**********************************************************************************************************/
staticOS_MEM      *OSMemFreeList;            /* Pointer to free list of memory partitions            */staticOS_MEM       OSMemTbl;/* Storage for memory partition manager               *//*$PAGE*/

/***********************************************************************************************************                                        CREATE A MEMORY PARTITION** Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.** Arguments   : addr   is the starting address of the memory partition**               nblks    is the number of memory blocks to create from the partition.**               blksizeis the size (in bytes) of each block in the memory partition.**               err      is a pointer to a variable containing an error message which will be set by*                        this function to either:*             *                        OS_NO_ERR            if the memory partition has been created correctly.*                        OS_MEM_INVALID_PARTno free partitions available*                        OS_MEM_INVALID_BLKSuser specified an invalid number of blocks (must be >= 2)*                        OS_MEM_INVALID_SIZEuser specified an invalid block size *                                             (must be greater than the size of a pointer)* Returns    : != (OS_MEM *)0is the partition was created *            == (OS_MEM *)0if the partition was not created because of invalid arguments or, no*                              free partition is available.**********************************************************************************************************/
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err){    OS_MEM*pmem;    INT8U   *pblk;    void   **plink;    INT32U   i;    //注意这里 (INT8U *)addr 和 (INT8U)*addr 完全不同啊啊,前者 addr是指向的一个地址,而这个地址内数据不知道是什么类型的    //所以(INT8U *)说明这个地址的内容是INT8U型的,(INT8U *)addr 表示的是一个新的addr,而后面(INT8U)*addr 表示把 *addr转换成    //一个八位的无符号整形数据          if (nblks < 2) {                                  /* Must have at least 2 blocks per partition      */      *err = OS_MEM_INVALID_BLKS;      return ((OS_MEM *)0);    }    if (blksize < sizeof(void *)) {                   /* Must contain space for at least a pointer      */      *err = OS_MEM_INVALID_SIZE;      return ((OS_MEM *)0);    }//    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= (void **)pblk;      pblk   = pblk + blksize;    }    *plink = (void *)0;                               /* Last memory block points to NULL            *///    OS_ENTER_CRITICAL();    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      *///    OS_EXIT_CRITICAL();    *err   = OS_NO_ERR;    return (pmem);}/*$PAGE*//***********************************************************************************************************                                          GET A MEMORY BLOCK** Description : Get a memory block from a partition** Arguments   : pmem    is a pointer to the memory partition control block**               err   is a pointer to a variable containing an error message which will be set by this*                     function to either:**                     OS_NO_ERR         if the memory partition has been created correctly.*                     OS_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller** Returns   : A pointer to a memory block if no error is detected*               A pointer to NULL if an error is detected**********************************************************************************************************/
void *OSMemGet (OS_MEM *pmem, INT8U *err){    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          */      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            */    } else {//      OS_EXIT_CRITICAL();      *err = OS_MEM_NO_FREE_BLKS;                   /* No,Notify caller of empty memory partition*/      return ((void *)0);                           /*      Return NULL pointer to caller            */    }}/*$PAGE*//***********************************************************************************************************                                    INITIALIZE MEMORY PARTITION MANAGER** Description : This function is called by uC/OS-II to initialize the memory partition manager.Your*               application MUST NOT call this function.** Arguments   : none** Returns   : none**********************************************************************************************************/
void OSMemInit (void){    OS_MEM*pmem;    INT16U   i;

    pmem = (OS_MEM *)&OSMemTbl;                  /* Point to memory control block (MCB)         */    for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {   /* Init. list of free memory partitions          */      pmem->OSMemFreeList = (void *)&OSMemTbl; /* Chain list of free partitions               */      pmem->OSMemAddr   = (void *)0;            /* Store start address of memory partition       */      pmem->OSMemNFree    = 0;                      /* No free blocks                              */      pmem->OSMemNBlks    = 0;                      /* No blocks                                     */      pmem->OSMemBlkSize= 0;                      /* Zero size                                     */      pmem++;    }    OSMemTbl.OSMemFreeList = (void *)0;    OSMemFreeList                               = (OS_MEM *)&OSMemTbl;}/*$PAGE*//***********************************************************************************************************                                       RELEASE A MEMORY BLOCK** Description : Returns a memory block to a partition** Arguments   : pmem    is a pointer to the memory partition control block**               pblk    is a pointer to the memory block being released.** Returns   : OS_NO_ERR         if the memory block was inserted into the partition*               OS_MEM_FULL       if you are returning a memory block to an already FULL memory partition*                                 (You freed more blocks than you allocated!)**********************************************************************************************************/
INT8U OSMemPut (OS_MEM*pmem, void *pblk){//    OS_ENTER_CRITICAL();    if (pmem->OSMemNFree >= pmem->OSMemNBlks) {/* Make sure all blocks not already returned          *///      OS_EXIT_CRITICAL();      return (OS_MEM_FULL);           }    *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */    pmem->OSMemFreeList = pblk;    pmem->OSMemNFree++;                        /* One more memory block in this partition            *///    OS_EXIT_CRITICAL();    return (OS_NO_ERR);                        /* Notify caller that memory block was released       */}/*$PAGE*//***********************************************************************************************************                                          QUERY MEMORY PARTITION** Description : This function is used to determine the number of free memory blocks and the number of *               used memory blocks from a memory partition.** Arguments   : pmem    is a pointer to the memory partition control block**               pdata   is a pointer to a structure that will contain information about the memory*                     partition.** Returns   : OS_NO_ERR         Always returns no error.**********************************************************************************************************/
INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *ppdata){//    OS_ENTER_CRITICAL();    ppdata->OSAddr   = pmem->OSMemAddr;    ppdata->OSFreeList = pmem->OSMemFreeList;    ppdata->OSBlkSize= pmem->OSMemBlkSize;    ppdata->OSNBlks    = pmem->OSMemNBlks;    ppdata->OSNFree    = pmem->OSMemNFree;//    OS_EXIT_CRITICAL();    ppdata->OSNUsed    = ppdata->OSNBlks - ppdata->OSNFree;    return (OS_NO_ERR);                         }//#endif  


  OS_MEM.h#ifndef OS_MEM_H_
#define OS_MEM_H_
#include "stm32f10x.h"

#ifndef OS_MEM_C_
#define OS_MEM_Cx_extern
#else
#define OS_MEM_Cx_
#endif

#define OS_MAX_MEM_PART         4


#define OS_NO_ERR               0
#define OS_MEM_INVALID_PART   110
#define OS_MEM_INVALID_BLKS   111
#define OS_MEM_INVALID_SIZE   112
#define OS_MEM_NO_FREE_BLKS   113
#define OS_MEM_FULL             114


typedef unsigned charINT8U;         //无符号8位数
typedef unsigned int   INT16U;      //无符号16位数
typedef unsigned longINT32U;      //无符号32位数


typedef struct {                     /* MEMORY CONTROL BLOCK                                       */
    void   *OSMemAddr;               /* Pointer to beginning of memory partition                     */
    void   *OSMemFreeList;             /* Pointer to list of free memory blocks                        */
    INT32UOSMemBlkSize;            /* Size (in bytes) of each block of memory                      */
    INT32UOSMemNBlks;                /* Total number of blocks in this partition                     */
    INT32UOSMemNFree;                /* Number of memory blocks remaining in this partition          */
} OS_MEM;


typedef struct {
    void   *OSAddr;                  /* Pointer to the beginning address of the memory partition   */
    void   *OSFreeList;                /* Pointer to the beginning of the free list of memory blocks   */
    INT32UOSBlkSize;               /* Size (in bytes) of each memory block                         */
    INT32UOSNBlks;                   /* Total number of blocks in the partition                      */
    INT32UOSNFree;                   /* Number of memory blocks free                                 */
    INT32UOSNUsed;                   /* Number of memory blocks used                                 */
} OS_MEM_DATA;


OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err);
void *OSMemGet (OS_MEM *pmem, INT8U *err);
void OSMemInit (void);
INT8U OSMemPut (OS_MEM*pmem, void *pblk);
INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *ppdata);



#endif







uCOSII提供的内存管理实质  一,实际上就是用一些程序对一个二维的数组进行管理
  

  二,整个数组叫做 "内存分区"
  三,数组的行数代表内存块的个数

  四,数组的每一行叫做 "内存块",每一行的长度叫做内存块长度
  五,申请内存块,实际上就是返回数组某一行的首地址,
    咱可以把数据存储到那一行里面!
  六,每一次申请内存块的时候,内部会判断哪一行没有被申请过 
    然后把哪一行的首地址返回过来
使用  一,创建内存  定义了一个二维数组,行数20(20个内存块)  列数16(每一个内存块最大存储16个数据)    

  二,申请一个内存块
    

  三,往内存块里面存储数据
    


    实际上就是存储到了那个二维数组里面    现在数组的第一行存储了数据

    



  四,再申请一个,再存储数据
    
    现在数组的第二行存储了数据
    







  四,使用存储的数据    操作存储数据的首地址即可
    





总结  μCOS-II提供的内存管理实际上就是对一个二维的数组进行管理  事先先定义好内存块,和每个内存块长度  二维数组的行数代表内存块个数  二维数组的列数代表每个内存块的长度    申请内存块其实就是内部程序判断数组哪一行没有使用过  然后返回那一行的首地址  然后咱就可以往里面存数据注意  往里面存储数据的时候不得超出内存块长度(数组每一行的列数)  有人可能会问,如果我有很大的数据量呢??  办法1.用多个内存块存储  办法2.设置内存块的长度足够长
补充1(释放使用的内存块)  咱使用完某一个内存块存储的数据以后需要告诉内部程序  释放这个内存块,以便这个内存块可以再次被申请使用  OSMemPut (OS_MEM*pmem, void *pblk)  第一个参数: 内存指针  第二个参数:内存块指针  

  





补充2(查询内存分区信息)  

  







页: [1]
查看完整版本: 09-μCOS-II中内存管理程序使用说明