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

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

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

發(fā)布時間:2016-12-18 22:35  回復(fù):0  查看:2471   最后回復(fù):2016-12-18 22:35  

在嵌入式設(shè)備中,持續(xù)的調(diào)用malloc()free()容易產(chǎn)生內(nèi)存碎片,長時間的運行最終會導(dǎo)致內(nèi)存消耗殆盡。UCOS系統(tǒng)提供了一套內(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

您還未登錄,請先登錄

熱門帖子

最新帖子

?