日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

os_mem.c(全)

發布時間:2025/3/21 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 os_mem.c(全) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本篇介紹內存管理方面的內容,具體如下:
  • 簡單介紹內存管理
  • 新建內存單元OS_MEM ?*OSMemCreate (void *addr,INT32U nblks,INT32U ?blksize,INT8U ?*perr)
  • 獲得內存塊void ?*OSMemGet (OS_MEM ?*pmem,INT8U *perr)
  • 得到內存分區名稱INT8U ?OSMemNameGet (OS_MEM ? *pmem,INT8U ? **pname,INT8U ? ?*perr)
  • 給內存分區設置名稱
  • 釋放內存塊INT8U ?OSMemPut (OS_MEM ?*pmem,void ?*pblk)
  • 查詢內存分區信息INT8U ?OSMemQuery (OS_MEM *pmem,OS_MEM_DATA ?*p_mem_data)
  • 初始化內存分區管理void ?OS_MemInit (void)

內存管理介紹:

????我們都知道可以用malloc()和free()兩個函數動態地分配內存和釋放內存。但是,在嵌入式實時操作系統中,多次這樣做會把原來很大的一塊連續內存區域,逐漸地分割成許多非常小而且彼此又不相鄰的內存區域,即內存碎片。內存碎片的大量存在不利于我們后續再分配內存。

? ? 所以,在μC/OS-II中,操作系統把連續的大塊內存按分區來管理。每個分區中包含有整數個大小相同的內存塊。利用這種機制,μC/OS-II 對malloc()和free()函數進行了改進,使得它們可以分配和釋放固定大小的內存塊。這樣還有一個好處就是malloc()和free()函數的執行時間是固定的。

????在一個系統中可以有多個內存分區。這樣,用戶的應用程序就可以從不同的內存分區中得到不同大小的內存塊。但是,特定的內存塊在釋放時必須重新放回它以前所屬于的內存分區。顯然,采用這樣的內存管理算法,上面的內存碎片問題就得到了解決。

????為了便于內存的管理,在μC/OS-II中使用內存控制塊(memory control blocks)的數據結構來跟蹤每一個內存分區,系統中的每個內存分區都有它自己的內存控制塊。內存控制塊的定義如下(uc/os-ii中):

typedef struct os_mem { ?/* MEMORY CONTROL BLOCK ?內存控制塊 ? ?*/void ? *OSMemAddr; ?/* Pointer to beginning of memory partition 指向內存分區的開始的指針 */void ? *OSMemFreeList; /* Pointer to list of free memory blocks指向空閑內存塊的指針 */INT32U ?OSMemBlkSize; ? /* Size (in bytes) of each block of memory內存分區中每個塊的大小,用戶建立該內存分區時指定 */INT32U ?OSMemNBlks; ?/* Total number of blocks in this partition該內存分區塊的總數量*/INT32U ?OSMemNFree; ? /* Number of memory blocks remaining in this partition該分區剩余空閑塊的數量 */ #if OS_MEM_NAME_EN > 0uINT8U ?*OSMemName; ? ?/* Memory partition name內存分區的名字*/ #endif } OS_MEM; typedef struct os_mem_data {void *OSAddr;/* Pointer to the beginning address of the memory partition指向內存分區起始地址的指針*/void *OSFreeList;/* Pointer to the beginning of the free list of memory blocks指向空閑內存塊列表開始的指針 */INT32U OSBlkSize;/* Size (in bytes) of each memory block 每個內存塊的大小 */INT32U OSNBlks; /* Total number of blocks in the partition 該分區中塊的總數量 */INT32U OSNFree; /* Number of memory blocks free空閑內存塊的數量 */INT32U OSNUsed; /* Number of memory blocks used 已使用的內存塊的數量 */ } OS_MEM_DATA;

新建內存分區OS_MEM ?*OSMemCreate (void ? *addr,?INT32U ?nblks,INT32U ?blksize,INT8U ?*perr):

源代碼如下:

#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u) /*2018/2/23 ********************************************************************************************************* * CREATE A MEMORY PARTITION * 新建內存單元 * Description : Create a fixed-sized memory partition that will be managed by uC/OS-II. *描述:建立一個大小可調節的內存單元,uc/os-ii管理該單元 * Arguments : addr is the starting address of the memory partition *參數: --addr:內存單元的起始地址。內存區可以使用靜態數組或在初始化時使用malloc()函數建立 * nblks is the number of memory blocks to create from the partition.blksize is the size (in bytes) of each block in the memory partition. * --nblks:需要的內存塊的數目。塊的大小是內存分區每一塊的大小(字節為單位) * perr is a pointer to a variable containing an error message which will be set by * this function to either: * OS_ERR_NONE if the memory partition has been created correctly. * OS_ERR_MEM_INVALID_ADDR if you are specifying an invalid address for the memory * storage of the partition or, the block does not align * on a pointer boundary * OS_ERR_MEM_INVALID_PART no free partitions available * OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2) * OS_ERR_MEM_INVALID_SIZE user specified an invalid block size * - must be greater than the size of a pointer * - must be able to hold an integral number of pointers * --perr:指向錯誤碼的指針。可以設置為以下值:OS_ERR_NONE:內存分區成功建立。OS_ERR_MEM_INVALID_ADDR:指定了非法地址或者為空指針OS_ERR_MEM_INVALID_PART:沒有空閑的分區可以使用。OS_ERR_MEM_INVALID_BLKS:使用者指定了無效的內存塊(內存塊數要>=2)OS_ERR_MEM_INVALID_SIZE:使用者指定了無效的塊大小:-必須比指針大;-指針為整數值 * Returns : != (OS_MEM *)0 is the partition was created * == (OS_MEM *)0 if the partition was not created because of invalid arguments or, no * free partition is available.返回值:!= (OS_MEM *)0:內存分區成功創建。== (OS_MEM *)0:內存分區沒有被創建因為參數無效或者沒有可用的空閑分區。 ********************************************************************************************************* */OS_MEM *OSMemCreate (void *addr,INT32U nblks,INT32U blksize,INT8U *perr) {OS_MEM *pmem;/*指向內存控制塊的指針*/INT8U *pblk;/*每塊內存塊的起始地址*/void **plink;/*鏈接起始地址*/INT32U loops;INT32U i;/*內存包含的內存區數量*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (addr == (void *)0) { /*當內存起始地址為0時*/ *perr = OS_ERR_MEM_INVALID_ADDR;/*錯誤顯示為(非法地址,即地址為空指針,無效)*/return ((OS_MEM *)0);}if (((INT32U)addr & (sizeof(void *) - 1u)) != 0u){ *perr = OS_ERR_MEM_INVALID_ADDR;return ((OS_MEM *)0);}if (nblks < 2u) { /*內存塊至少為2*/ *perr = OS_ERR_MEM_INVALID_BLKS;return ((OS_MEM *)0);}if (blksize < sizeof(void *)) { /*每個內存塊至少容得一個指針(鏈接指針)*/ *perr = OS_ERR_MEM_INVALID_SIZE;/*否則顯示(內存塊大小不足以容納一個指針變量)*/return ((OS_MEM *)0);}#endifOS_ENTER_CRITICAL();/*進入中斷*/pmem = OSMemFreeList; /*得到空閑的內存分區*/if (OSMemFreeList != (OS_MEM *)0)/*有空閑的內存分區*/{ OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;/*指向下一個空余鏈接控制塊*/}OS_EXIT_CRITICAL();/*退出中斷*/if (pmem == (OS_MEM *)0) /*沒有獲得內存分區*/{ *perr = OS_ERR_MEM_INVALID_PART;return ((OS_MEM *)0);}/*獲得了內存分區*/plink = (void **)addr;/*/鏈接起始地址=內存分區起始地址*/pblk = (INT8U *)addr;loops = nblks - 1u;/*循環次數*/for (i = 0u; i < loops; i++) {pblk += blksize; /*每塊內存的起始地址=內存分區起始地址+每塊內存塊大小 */*plink = (void *)pblk;plink = (void **)pblk;}*plink = (void *)0;/*最后一個鏈接指針指為空 */pmem->OSMemAddr = addr; /* 存儲內存分區開始地址 */pmem->OSMemFreeList = addr; /*內存空閑列表指向內存分區起始地址*/pmem->OSMemNFree = nblks;/* 分區中空閑內存塊數量=需要的內存塊數目 */pmem->OSMemNBlks = nblks;/*總的內存塊數量=需要的內存塊數目*/pmem->OSMemBlkSize = blksize;/*內存塊大小 */*perr = OS_ERR_NONE;return (pmem); }

其中一些語句解釋如下:(個人理解)

1.

pmem = OSMemFreeList; /*得到空閑的內存分區*/if (OSMemFreeList != (OS_MEM *)0)/*有空閑的內存分區*/{ OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;/*更新空閑內存列表*/}OS_EXIT_CRITICAL();/*退出中斷*/if (pmem == (OS_MEM *)0) /*沒有獲得內存分區*/{ *perr = OS_ERR_MEM_INVALID_PART;return ((OS_MEM *)0);}

這里想說一下:我們看到判斷了兩次,第一次是判斷有沒有空閑的內存分區。這個是為了更新空閑列表設置的。第二次是判斷有沒有獲得內存分區。有空閑分區我們不一定會獲得,所以需要進行確認。

2.for循環中:

for (i = 0u; i < loops; i++) {pblk += blksize; /*每塊內存的起始地址=內存分區起始地址+每塊內存塊大小 */*plink = (void *)pblk;plink = (void **)pblk;}

這里兩行語句沒有注釋,因為覺得說不清楚。個人理解是:


1).pblk每次進行計算,保存的是下一個內存塊起始地址。

2)plink指向pblk指向的那個地址;

3)plink本身作為下一個塊的鏈接。


獲得內存塊void ?*OSMemGet (OS_MEM ?*pmem,INT8U ? *perr):

/*$PAGE*/ /*2018/2/23 ********************************************************************************************************* * GET A MEMORY BLOCK * ????????獲得內存塊 * Description : Get a memory block from a partition *描述:從內存分區得到內存塊 * Arguments : pmem is a pointer to the memory partition control block *參數: --pmem:指向內存分區控制塊的指針 * perr is a pointer to a variable containing an error message which will be set by this * function to either: * OS_ERR_NONE if the memory partition has been created correctly. * OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' * --perr:包含錯誤碼的指針:OS_ERR_NONE:內存分區被成功創建OS_ERR_MEM_NO_FREE_BLKS:沒有空余的內存塊可以分配OS_ERR_MEM_INVALID_PMEM:pmem為空指針。 * 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 *perr) {void *pblk;/*指向內存塊的指針*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (pmem == (OS_MEM *)0) { *perr = OS_ERR_MEM_INVALID_PMEM;return ((void *)0);}#endifOS_ENTER_CRITICAL();/*進入中斷*/if (pmem->OSMemNFree > 0u) /*有空閑的內存塊*/{ pblk = pmem->OSMemFreeList; /*pblk指向空閑的內存塊 */pmem->OSMemFreeList = *(void **)pblk;/*調整空閑內存列表*/pmem->OSMemNFree--;/*空閑內存塊數量減1*/OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_NONE;return (pblk); /* 返回內存塊 */}/*如果沒有空閑的內存塊*/OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_MEM_NO_FREE_BLKS; /*設置錯誤碼*/return ((void *)0); /*返回空*/ }

得到內存分區名稱INT8U ?OSMemNameGet (OS_MEM ? *pmem,INT8U ? **pname,INT8U ? ?*perr):

/*$PAGE*/ /*2018/2/23 ********************************************************************************************************* * GET THE NAME OF A MEMORY PARTITION * 得到內存分區名稱 * Description: This function is used to obtain the name assigned to a memory partition. *描述:該函數是用來獲得內存分區的名稱 * Arguments : pmem is a pointer to the memory partition *參數: --pmem:指向內存分區的指針 * pname is a pointer to a pointer to an ASCII string that will receive the name of the memory partition. * --pname:指向內存分區名稱的指針 * perr is a pointer to an error code that can contain one of the following values: * OS_ERR_NONE if the name was copied to 'pname' * OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem' * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname' * OS_ERR_NAME_GET_ISR You called this function from an ISR * --perr:指向錯誤碼的指針:OS_ERR_NONE:名字被復制到了pname;OS_ERR_MEM_INVALID_PMEM:pmem為空指針OS_ERR_PNAME_NULL:pname為空指針OS_ERR_NAME_GET_ISR:從中斷服務子程序中調用該函數 * Returns : The length of the string or 0 if 'pmem' is a NULL pointer. 返回值:如果pname為空指針返回0,否則返回名稱的長度 ********************************************************************************************************* */#if OS_MEM_NAME_EN > 0u INT8U OSMemNameGet (OS_MEM *pmem,INT8U **pname,INT8U *perr) {INT8U len;/*存儲名稱的長度*/#if OS_CRITICAL_METHOD == 3u OS_CPU_SR cpu_sr = 0u;#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();}#endif#if OS_ARG_CHK_EN > 0uif (pmem == (OS_MEM *)0) { *perr = OS_ERR_MEM_INVALID_PMEM;return (0u);}if (pname == (INT8U **)0) { *perr = OS_ERR_PNAME_NULL;return (0u);}#endifif (OSIntNesting > 0u) { *perr = OS_ERR_NAME_GET_ISR;return (0u);}OS_ENTER_CRITICAL();/(進入中斷*pname = pmem->OSMemName;/*將名稱賦給pname*/len = OS_StrLen(*pname);/*求出名稱的長度*/OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_NONE;return (len);/*返回長度*/ } #endif

給中斷分區設置名稱void ?OSMemNameSet (OS_MEM ?*pmem,INT8U ? *pname,INT8U ? *perr):(部分)

OS_ENTER_CRITICAL();/*進入中斷*/pmem->OSMemName = pname;/*設置名稱*/OS_EXIT_CRITICAL();/*退出中斷*/*perr = OS_ERR_NONE;

釋放內存塊INT8U ?OSMemPut (OS_MEM ?*pmem,?void ?*pblk)(部分):

OS_ENTER_CRITICAL();/*進入中斷*/if (pmem->OSMemNFree >= pmem->OSMemNBlks)/*釋放的塊數大于分配的塊數*/{ OS_EXIT_CRITICAL();/*退出中斷*/return (OS_ERR_MEM_FULL);/*返回錯誤類型*/}/*釋放的塊數小于分配的塊數,可以釋放*/*(void **)pblk = pmem->OSMemFreeList; /*將釋放的塊插入到空閑內存列表中*/pmem->OSMemFreeList = pblk;pmem->OSMemNFree++;/* 將空閑塊數目加1 */OS_EXIT_CRITICAL();/*退出中斷*/return (OS_ERR_NONE);

查詢內存分區信息INT8U ?OSMemQuery (OS_MEM *pmem,OS_MEM_DATA ?*p_mem_data):(部分)

OS_ENTER_CRITICAL();/*進入中斷*/p_mem_data->OSAddr = pmem->OSMemAddr;p_mem_data->OSFreeList = pmem->OSMemFreeList;p_mem_data->OSBlkSize = pmem->OSMemBlkSize;p_mem_data->OSNBlks = pmem->OSMemNBlks;p_mem_data->OSNFree = pmem->OSMemNFree;OS_EXIT_CRITICAL();p_mem_data->OSNUsed = p_mem_data->OSNBlks - p_mem_data->OSNFree;

其實就是進行了最上面兩個結構體內容的賦值。

初始化內存分區管理void ?OS_MemInit (void):

/*$PAGE*/ /*2018/2/23 ********************************************************************************************************* * 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. *,描述:該函數由uc/os-ii調用,用來初始化內存分區管理。你的應用程序不能調用該函數。 * Arguments : none *參數:無 * Returns : none *返回值:無 * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it. 注釋:該功能為內部函數 ********************************************************************************************************* */void OS_MemInit (void) {#if OS_MAX_MEM_PART == 1u/*如果內存分區只有一個*/OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /* 清除內存分區表 */OSMemFreeList = (OS_MEM *)&OSMemTbl[0]; /*指針指向空閑列表的開始 */#if OS_MEM_NAME_EN > 0uOSMemFreeList->OSMemName = (INT8U *)"?"; /* 名稱初始化為未命名 */#endif#endif#if OS_MAX_MEM_PART >= 2u/*如果不止一個分區*/OS_MEM *pmem;/*指向內存分區的指針*/INT16U i;OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl)); /*清除內存分區表 */for (i = 0u; i < (OS_MAX_MEM_PART - 1u); i++)/*初始化空閑內存分區表*/{ pmem = &OSMemTbl[i]; /*指向內存控制塊(MCB)*/pmem->OSMemFreeList = (void *)&OSMemTbl[i + 1u]; /*更新空閑分區列表 */#if OS_MEM_NAME_EN > 0upmem->OSMemName = (INT8U *)(void *)"?";/*名稱設為未命名*/#endif}pmem = &OSMemTbl[i];pmem->OSMemFreeList = (void *)0;/*初始化最后一個節點*/#if OS_MEM_NAME_EN > 0upmem->OSMemName = (INT8U *)(void *)"?";#endifOSMemFreeList = &OSMemTbl[0];/* 將空閑列表指針指向內存分區表的首地址*/ #endif } #endif

到這里os_mem.c文件就讀完了。

===============================================================

===============================================================


總結

以上是生活随笔為你收集整理的os_mem.c(全)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。