新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > μC/OS-II的內(nèi)存管理

        μC/OS-II的內(nèi)存管理

        作者: 時間:2016-10-08 來源:網(wǎng)絡(luò) 收藏

        我們知道,在ANSIC中可以用malloc()和free()兩個函數(shù)動態(tài)地分配內(nèi)存和釋放內(nèi)存。但

        本文引用地址:http://www.104case.com/article/201610/305740.htm

        是,在嵌入式實時操作系統(tǒng)中,多次這樣做會把原來很大的一塊連續(xù)內(nèi)存區(qū)域,逐漸地分割成

        許多非常小而且彼此又不相鄰的內(nèi)存區(qū)域,也就是內(nèi)存碎片。由于這些碎片的大量存在,使得

        程序到后來連非常小的內(nèi)存也分配不到。在4.02節(jié)的任務(wù)堆棧中,我們講到過用malloc()函

        數(shù)來分配堆棧時,曾經(jīng)討論過內(nèi)存碎片的問題。另外,由于內(nèi)存管理算法的原因,malloc()和

        free()函數(shù)執(zhí)行時間是不確定的。

        在μC/OS-II中,操作系統(tǒng)把連續(xù)的大塊內(nèi)存按分區(qū)來管理。每個分區(qū)中包含有整數(shù)個大小相同

        的內(nèi)存塊,如同圖F7.1。利用這種機制,μC/OS-II對malloc()和free()函數(shù)進行了改進,使

        得它們可以分配和釋放固定大小的內(nèi)存塊。這樣一來,malloc()和free()函數(shù)的執(zhí)行時間也是

        固定的了。

        如圖F7.2,在一個系統(tǒng)中可以有多個內(nèi)存分區(qū)。這樣,用戶的應(yīng)用程序就可以從不同的內(nèi)存

        分區(qū)中得到不同大小的內(nèi)存塊。但是,特定的內(nèi)存塊在釋放時必須重新放回它以前所屬于的內(nèi)

        存分區(qū)。顯然,采用這樣的內(nèi)存管理算法,上面的內(nèi)存碎片問題就得到了解決。

        圖F7.1內(nèi)存分區(qū)——Figure7.1

        圖F7.2多個內(nèi)存分區(qū)——Figure7.2

        內(nèi)存控制塊

        為了便于內(nèi)存的管理,在μC/OS-II中使用內(nèi)存控制塊(memorycONtrolblocks)的數(shù)據(jù)結(jié)構(gòu)來跟蹤每一個內(nèi)存分區(qū),系統(tǒng)中的每個內(nèi)存分區(qū)都有它自己的內(nèi)存控制塊。程序清單L7.1是內(nèi)存控制塊的定義。

        程序清單L7.1內(nèi)存控制塊的數(shù)據(jù)結(jié)構(gòu)

        typedefSTruct{

        void*OSMemAddr;

        void*OSMemFreeList;

        INT32UOSMemBlkSize;

        INT32UOSMemNBlks;

        INT32UOSMemNFree;

        }OS_MEM;

        .OSMemAddr是指向內(nèi)存分區(qū)起始地址的指針。它在建立內(nèi)存分區(qū)[見7.1節(jié),建立一個內(nèi)存分區(qū),OSMemCreate()]時被初始化,在此之后就不能更改了。

        .OSMemFreeList是指向下一個空閑內(nèi)存控制塊或者下一個空閑的內(nèi)存塊的指針,具體含義要根據(jù)該內(nèi)存分區(qū)是否已經(jīng)建立來決定[見7.1節(jié)]。

        .OSMemBlkSize 是內(nèi)存分區(qū)中內(nèi)存塊的大小,是用戶建立該內(nèi)存分區(qū)時指定的[見7.1節(jié)]。

        .OSMemNBlks是內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)量,也是用戶建立該內(nèi)存分區(qū)時指定的[見7.1節(jié)]。

        .OSMemNFree是內(nèi)存分區(qū)中當(dāng)前可以得空閑內(nèi)存塊數(shù)量。

        如果要在μC/OS-II中使用內(nèi)存管理,需要在OS_CFG.H文件中將開關(guān)量OS_MEM_EN設(shè)置為1。這樣μC/OS-II在啟動時就會對內(nèi)存管理器進行初始化[由OSInit()調(diào)用OSMemInit()實現(xiàn)]。該初始化主要建立一個圖F7.3所示的內(nèi)存控制塊鏈表,其中的常數(shù)OS_MAX_MEM_PART(見文件OS_CFG.H)定義了最大的內(nèi)存分區(qū)數(shù),該常數(shù)值至少應(yīng)為2。

        圖F7.3空閑內(nèi)存控制塊鏈表——Figure7.3

        建立一個內(nèi)存分區(qū),OSMemCreate()在使用一個內(nèi)存分區(qū)之前,必須先建立該內(nèi)存分區(qū)。這個操作可以通過調(diào)用OSMemCreate()函數(shù)來完成。程序清單L7.2說明了如何建立一個含有100個內(nèi)存塊、每個內(nèi)存塊32字節(jié)的內(nèi)存分區(qū)。

        程序清單L7.2建立一個內(nèi)存分區(qū)

        OS_MEM*CommTxBuf;

        INT8UCommTxPart[100][32];

        voidmain(void)

        {

        INT8Uerr;

        OSInit();

        .

        .

        CommTxBuf=OSMemCreate(CommTxPart,100,32,err);

        .

        .

        OSStart();

        }

        程序清單L7.3是OSMemCreate()函數(shù)的源代碼。該函數(shù)共有4個參數(shù):內(nèi)存分區(qū)的起始地址、分區(qū)內(nèi)的內(nèi)存塊總塊數(shù)、每個內(nèi)存塊的字節(jié)數(shù)和一個指向錯誤信息代碼的指針。如果OSMemCreate()操作失敗,它將返回一個NULL指針。否則,它將返回一個指向內(nèi)存控制塊的指針。對內(nèi)存管理的其它操作,象OSMemGet(),OSMemPut(),OSMemQuery()函數(shù)等,都要通過該指針進行。

        每個內(nèi)存分區(qū)必須含有至少兩個內(nèi)存塊[L7.3(1)],每個內(nèi)存塊至少為一個指針的大小,因為同一分區(qū)中的所有空閑內(nèi)存塊是由指針串聯(lián)起來的[L7.3(2)]。接著,OSMemCreate()從系統(tǒng)中的空閑內(nèi)存控制塊中取得一個內(nèi)存控制塊[L7.3(3)],該內(nèi)存控制塊包含相應(yīng)內(nèi)存分區(qū)的運行信息。OSMemCreate()必須在有空閑內(nèi)存控制塊可用的情況下才能建立一個內(nèi)存分區(qū)[L7.3(4)]。在上述條件均得到滿足時,所要建立的內(nèi)存分區(qū)內(nèi)的所有內(nèi)存塊被鏈接成一個單向的鏈表[L7.3(5)]。然后,在對應(yīng)的內(nèi)存控制塊中填寫相應(yīng)的信息[L7.3(6)]。完成上述各動作后,OSMemCreate()返回指向該內(nèi)存塊的指針。該指針在以后對內(nèi)存塊的操作中使用[L7.3(6)]。

        程序清單L7.3OSMemCreate()

        OS_MEM*OSMemCreate(void*addr,INT32Unblks,INT32Ublksize,INT8U*err)

        {

        OS_MEM*pmem;

        INT8U*pblk;

        void**plink;

        INT32Ui;

        if(nblks2){(1)

        *err=OS_MEM_INVALID_BLKS;

        return((OS_MEM*)0);

        }

        if(blksize

        *err=OS_MEM_INVALID_SIZE;

        return((OS_MEM*)0);

        }

        OS_ENTER_CRITICAL();

        pmem=OSMemFreeList;(3)

        if(OSMemFreeList!=(OS_MEM*)0){

        OSMemFreeList=(OS_MEM*)OSMemFreeList->OSMemFreeList;

        }

        OS_EXIT_CRITICAL();

        if(pmem==(OS_MEM*)0){(4)

        *err=OS_MEM_INVALID_PART;

        return((OS_MEM*)0);

        }

        plink=(void**)addr;(5)

        pblk=(INT8U*)addr+blksize;


        上一頁 1 2 3 下一頁

        關(guān)鍵詞:

        評論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 宁国市| 德格县| 革吉县| 石城县| 沅陵县| 杨浦区| 固安县| 延川县| 韶关市| 东乌| 沅江市| 二连浩特市| 藁城市| 灵山县| 滦南县| 沙河市| 弋阳县| 武冈市| 玛曲县| 阿瓦提县| 鄂尔多斯市| 项城市| 天全县| 钟祥市| 宜都市| 鄂托克前旗| 双鸭山市| 利津县| 泗阳县| 抚宁县| 伽师县| 大悟县| 拜泉县| 卢湾区| 陆丰市| 鹿泉市| 海盐县| 瑞昌市| 克拉玛依市| 汽车| 台山市|