99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

UCOS學(xué)習(xí)之內(nèi)存管理

發(fā)布時間:2017-05-27 15:49  回復(fù):0  查看:2114   最后回復(fù):2017-05-27 15:49  

本文和大家分享的主要是UCOS中的內(nèi)存管理相關(guān)內(nèi)容,一起來看看吧,希望對大家學(xué)習(xí)ucos有所幫助。

  在 嵌 入 式設(shè)備中,持續(xù)的調(diào)用malloc()free()容易產(chǎn)生內(nèi)存碎片,長時間的運行最終會導(dǎo)致內(nèi)存消耗殆盡。UCOS提供了一套內(nèi)存管理機制,在系統(tǒng)初始化的時候就分配好內(nèi)存空間,將所有可用的空間組織成鏈表,需要申請內(nèi)存的時候直接從鏈表中申請,釋放內(nèi)存的時候直接將內(nèi)存歸還到空余內(nèi)存鏈表中即可。使用這種方法不僅避免了內(nèi)存碎片的產(chǎn)生,而且使得在常數(shù)時間內(nèi)分配內(nèi)存空間成為可能。

UCOS中內(nèi)存管理的結(jié)構(gòu)體是OS_MEM,具體結(jié)構(gòu)如下:

typedef struct os_mem  //內(nèi)存控制塊{

void   *OSMemAddr; //指向內(nèi)存分區(qū)的首地址

void   *OSMemFreeList; //該內(nèi)存分區(qū)的block鏈表的表頭

INT32U  OSMemBlkSize;  //每一個block的大小

INT32U  OSMemNBlks; //該分區(qū)中block的數(shù)目

INT32U  OSMemNFree; //該分區(qū)中空閑block的數(shù)目

} OS_MEM;

  在UCOS中,一個內(nèi)存分區(qū)被劃分成很多個大小相等的內(nèi)存塊,這些內(nèi)存塊鏈接成鏈表,鏈表的表頭存于OSMemFreeList中。

  比如一個有4個內(nèi)存塊,每個內(nèi)存塊128bit的內(nèi)存分區(qū)Memoy如下:

INT32U Memory[4][4]

UCOS的思路是我們將要分配的空間組織成二維數(shù)組,然后二維數(shù)組的每一行就是一個block,二維數(shù)組的列數(shù)既是block的大小。

Memory的第一個block的首地址是Memor[0]

Memory的第二個block的首地址是Memory[1]

Memory的第三個block的首地址是Memory[2]

Memory的第四個block的首地址是Memory[3]

  為了管理方便我們在每一個block的開頭存儲下一個block的地址,這樣就把所有的block串接成了單鏈表。

  第一個block的開頭存儲Memory[1]

  第一個block的開頭存儲Memory[2]

  第一個block的開頭存儲Memory[3]

  第一個block的開頭存儲NULL

  最終結(jié)果如下圖:

UCOS學(xué)習(xí)之內(nèi)存管理

UCOS中創(chuàng)建內(nèi)存分區(qū)的核心代碼如下(代碼取自OSMemCreate)

//內(nèi)存分區(qū)的首地址

plink = (void **)addr;

//第二個block的地址

pblk  = (INT8U *)((INT32U)addr + blksize);

for (i = 0; i < (nblks - 1); i++)

{

//每一個block的開頭存放下一個block的首地址

*plink = (void *)pblk;

//更新指針而已

plink = (void **)pblk;

pblk  = (INT8U *)((INT32U)pblk + blksize);

}

//最后一個block指向NULL

*plink  = (void *)0;

  上述代碼的核心就在于*pblink = (void*)pblk;每一個block開頭存放下一個block的地址,這樣便把所有的block組織成了一條鏈表。

  申請一個內(nèi)存塊:

//還有內(nèi)存可以分配

if (pmem->OSMemNFree > 0)

{

//獲取一個block

pblk = pmem->OSMemFreeList;

//使鏈表表頭指向這個block的下一個block

pmem->OSMemFreeList = *(void **)pblk;

//更新內(nèi)存塊的數(shù)量

pmem->OSMemNFree--;

}

  代碼的核心就在于pmem->OSMemFreeList = *(void **)pblk;  因為pblk指向該block,該block的首地址存放的是下一個block的地址,所以這句實際上讓空余鏈表的表頭指向了下一個block。

  刪除一個內(nèi)存塊:

//在將要刪除的內(nèi)存塊的首地址存放block表頭的地址

*(void **)pblk  = pmem->OSMemFreeList;

//更新鏈表表頭

pmem->OSMemFreeList = pblk;

//更新可用內(nèi)存塊的數(shù)目

pmem->OSMemNFree++;

  代碼的核心就是*(void **)pblk      = pmem->OSMemFreeList;在將要刪除的block的開頭存放鏈表的表頭,即相當(dāng)于把這個block鏈接到了空余鏈表的表頭中。

 

 來源:CSDN

您還未登錄,請先登錄

熱門帖子

最新帖子

?