<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > UC/OS-II的內存管理OSMemCreate()分析

UC/OS-II的內存管理OSMemCreate()分析

作者: 時(shí)間:2016-12-01 來(lái)源:網(wǎng)絡(luò ) 收藏
我們在寫(xiě)應用程序的過(guò)程中通常都是采用一個(gè)malloc/free系列函數進(jìn)行內存的管理,這樣分配的內存空間是從應用程序的??臻g分配處理,一般而言我們在寫(xiě)程序的過(guò)程中要對內存空間進(jìn)行適時(shí)的釋放,才不至于導致??臻g的不足,當然這樣也會(huì )導致內存垃圾的產(chǎn)生,因為不同大小的內存分配因為對齊等原因導致很多的內存不能再使用,進(jìn)而使得系統的可用內存越來(lái)越小,因此在實(shí)時(shí)操作系統中通常都需要創(chuàng )建自己的內存管理操作。
uc/os-II中的內存管理主要是采用內存分區控制塊實(shí)現的,具體的實(shí)現過(guò)程如下:

本文引用地址:http://dyxdggzs.com/article/201612/324517.htm

/*
關(guān)于內存控制塊的結構體,
用來(lái)跟蹤每一個(gè)內存分區
每一個(gè)分區可以分成很多個(gè)小的內存塊
每一個(gè)內存塊的大小都是相同的
*/
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
typedef struct { /* MEMORY CONTROL BLOCK */
/*內存的起始地址*/
void *OSMemAddr; /* Pointer to beginning ofmemorypartition */
/*
鏈表指針,
能夠快速的實(shí)現內存的控制
*/
void *OSMemFreeList; /* Pointer to list of free memory blocks */
/*每一個(gè)內存塊的大小*/
INT32U OSMemBlkSize; /* Size (in bytes) of each block of memory */
/*存在的內存塊數量*/
INT32U OSMemNBlks; /* Total number of blocks in this partition */
/*空閑的內存空間*/
INT32U OSMemNFree; /* Number ofmemoryblocks remaining in this partition */
} OS_MEM;

基本的實(shí)現思想就是將內存分區分解成很多的大小相同的內存塊,然后OSMemFreeList將所有的內存塊鏈接起來(lái),但是此處的鏈接與我們常用的鏈表存在一定的差別,這也是內存管理中常用的技巧之一,即在當前塊的起始地址處存放下一個(gè)內存塊的地址,這樣就能比較快速的實(shí)現內存的管理。在uc/os-II的內存管理代碼的OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)函數中存在一些代碼難點(diǎn)。特別是強制類(lèi)型轉換的使用,在uc/os-II中我們看見(jiàn)了大量的強制類(lèi)型轉換問(wèn)題,下面就做一下簡(jiǎn)要的分析:

OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPUstatusregister */
OS_CPU_SR cpu_sr;
#endif
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U i;

/*檢測參數的正確性*/
#if OS_ARG_CHK_EN > 0
if (addr == (void *)0) { /* Must pass a valid address for the memory part. */
*err = OS_MEM_INVALID_ADDR;
return ((OS_MEM *)0);
}
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);
}
#endif

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);
}
/*
將一個(gè)分區的各個(gè)內存小塊鏈接起來(lái),
形成一個(gè)鏈表
*/
plink = (void **)addr; /* Create linked list of free memoryblocks */
/*得到一個(gè)固定的*/
pblk = (INT8U *)addr + blksize;
for (i = 0; i < (nblks - 1); i++) {
/*在當前的地址處保存下一個(gè)內存塊的地址*/
*plink = (void *)pblk;
/*將指針指向下一個(gè)內存塊*/
plink = (void **)pblk;
/*得到第三個(gè)內存塊的地址*/
pblk = pblk + blksize;
}
/*
將最后一個(gè)內存塊的下一個(gè)地址設置為NULL;
*/
*plink = (void *)0; /* Last memoryblockpoints to NULL */
/*得到內存分區的起始地址*/
pmem->OSMemAddr = addr; /* Store start address ofmemorypartition */
/*
將內存塊的鏈表頭指向當前地址
通過(guò)鏈表能夠快速的找到下一個(gè)內存塊的地址
只需要對鏈表取地址,
然后將指針指向該地址就能實(shí)現快速的切換
*/
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 eachmemoryblocks */
*err = OS_NO_ERR;
return (pmem);
}

上面的代碼大致的意思就是完成內存塊的鏈接以及內存分區控制單元的初始化操作,但是有幾句代碼存在一定的理解難度。

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; /* Lastmemoryblockpoints to NULL */

下面幾句代碼中存在大量的強制類(lèi)型轉換,我們一句一句的分析,plink=(void**)addr的意思是將傳遞進(jìn)來(lái)的地址強制轉換,原因是因為plink是一個(gè)存儲在函數棧中的變量,它指向了addr指向的地址,而該地址處將來(lái)存儲的也是一個(gè)地址,因此可以看做二維指針,而addr只是一維指針,因此需要強制類(lèi)型轉換為二維指針。

引用:在聲明的時(shí)候,plink是二維指針,在這里將addr強制的轉換成二維指針再賦值給plink的原因是:讓addr以前指向的內容讓編譯器解釋成地址,也就是一個(gè)指針,如果不做這個(gè)強制轉換,以前addr指向的內容就不是一個(gè)地址,也就是不是指針,在這個(gè)函數當中,我們想把addr指向的二維數組,分割成大小相同的若干塊,就必須用指針把它們鏈接起來(lái),所以將addr強制轉換成二維指針,然后賦值給plink,然后讓plink去執行連接的操作,也就是在以前addr指向的地方放上指針;plink本身是存放在棧上的,plink這個(gè)符號的值是指向addr的,*plink就是取plink指向地址單元的內容,而 plink指向地址單元的內容是一個(gè)地址,即是一個(gè)指針,plink指向地址單元的內容也就是addr指向地址單元的內容,但由于addr是一維指針,所以它指向的內容不會(huì )被解釋成一個(gè)地址,而是一般的內容?,F在*plink就是把addr所在存儲單元的內容解釋成一個(gè)指針,并且將下一個(gè)block的首地址賦值給此存儲單元,理解了這點(diǎn)就可以理解下面的源代碼了,同時(shí)對C里面指針的概念又有了進(jìn)一步的認識。http://blog.csdn.net/uestczhangchao/article/details/5589476

pblk=(INT8U*)addr+blksize;這句代碼其中暗含了我們對指針加減操作的基本理解,因為在uc/OS-II中是按照字節作為內存塊分布的,所以進(jìn)行了INT8U*的強制類(lèi)型轉換,因為只有這樣才能保證addr+blksize的操作是增加多少個(gè)字節的數據。因為C語(yǔ)言中指針的加減是與其指向的類(lèi)型的內存空間密切相關(guān)的,比如int * p = 0; p ++;此時(shí)的p = 4;而當char *p = 0; p ++; 此時(shí)的p = 1;這就說(shuō)明了指針的加減必須注意數據的類(lèi)型,而不能直接對void*類(lèi)型的指針進(jìn)行加減操作。

*plink=(void*)pblk;因為plink是一個(gè)棧中變量,而對plink取進(jìn)行解引用,實(shí)際上就是得到addr的值,但是*plink是一個(gè)地址,還是一個(gè)指針,因此需要強制類(lèi)型轉換。

plink=(void**)pblk;上面的代碼已經(jīng)分析。

基本的思想就是需要注意常數轉換為指針的方式方法:int* p = (int *)0x45342341;int **p = (int **)0x45342341;指針的引入主要就是為了解決內存問(wèn)題,因此對內存的管理直接體現了對指針的理解深度。



關(guān)鍵詞: UCOS-II內存管理OSMemCreat

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>