版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、第第 1212 章章 內(nèi)存管理內(nèi)存管理.1內(nèi)存控制塊.2建立一個內(nèi)存分區(qū),OSMEMCREATE().312.2 分配一個內(nèi)存塊,OSMEMGET().512.3 釋放一個內(nèi)存塊,OSMEMPUT().612.4 查詢一個內(nèi)存分區(qū)的狀態(tài),OSMEMQUERY().712.5 USING MEMORY PARTITIONS.812.6 等待一個內(nèi)存塊.9第第 7 7 章章第第 1212 章章 內(nèi)存管理內(nèi)存管理我們知道,在我們知道,在 ANSIANSI C C 中可以用中可以用 malloc()malloc()和和 free()free()兩個函數(shù)動態(tài)地分配內(nèi)存和釋放內(nèi)存。但是,兩個函數(shù)動態(tài)地分配
2、內(nèi)存和釋放內(nèi)存。但是,在嵌入式實時操作系統(tǒng)中,多次這樣做會把原來很大的一塊連續(xù)內(nèi)存區(qū)域,逐漸地分割成許多在嵌入式實時操作系統(tǒng)中,多次這樣做會把原來很大的一塊連續(xù)內(nèi)存區(qū)域,逐漸地分割成許多非常小而且彼此又不相鄰的內(nèi)存區(qū)域,也就是內(nèi)存碎片。由于這些碎片的大量存在,使得程序非常小而且彼此又不相鄰的內(nèi)存區(qū)域,也就是內(nèi)存碎片。由于這些碎片的大量存在,使得程序到后來連非常小的內(nèi)存也分配不到。在節(jié)的任務堆棧中,我們講到過用到后來連非常小的內(nèi)存也分配不到。在節(jié)的任務堆棧中,我們講到過用 malloc()malloc()函數(shù)來分配堆函數(shù)來分配堆棧時,曾經(jīng)討論過內(nèi)存碎片的問題。另外,由于內(nèi)存管理算法的原因,棧時,
3、曾經(jīng)討論過內(nèi)存碎片的問題。另外,由于內(nèi)存管理算法的原因,malloc()malloc()和和 free()free()函數(shù)函數(shù)執(zhí)行時間是不確定的。執(zhí)行時間是不確定的。在在 C/OS-IIC/OS-II 中中,操作系統(tǒng)把連續(xù)的大塊內(nèi)存按分區(qū)來管理。每個分區(qū)中包含有整數(shù)個大小相操作系統(tǒng)把連續(xù)的大塊內(nèi)存按分區(qū)來管理。每個分區(qū)中包含有整數(shù)個大小相同的內(nèi)存塊,同的內(nèi)存塊,如同圖如同圖 F12.1F12.1。利用這種機制,。利用這種機制,C/OS-IIC/OS-II 對對 malloc()malloc()和和 free()free()函數(shù)進行了改進,函數(shù)進行了改進,使得它們可以分配和釋放固定大小的內(nèi)存塊。
4、這樣一來,使得它們可以分配和釋放固定大小的內(nèi)存塊。這樣一來,malloc()malloc()和和 free()free()函數(shù)的執(zhí)行時間也函數(shù)的執(zhí)行時間也是固定的了。是固定的了。如圖如圖 F12.2F12.2,在一個系統(tǒng)中可以有多個內(nèi)存分區(qū)。這樣,用戶的應用程序就可以從不同的內(nèi)存,在一個系統(tǒng)中可以有多個內(nèi)存分區(qū)。這樣,用戶的應用程序就可以從不同的內(nèi)存分區(qū)中得到不同大小的內(nèi)存塊。但是,特定的內(nèi)存塊在釋放時必須重新放回它以前所屬于的內(nèi)分區(qū)中得到不同大小的內(nèi)存塊。但是,特定的內(nèi)存塊在釋放時必須重新放回它以前所屬于的內(nèi)存分區(qū)。顯然,采用這樣的內(nèi)存管理算法,上面的內(nèi)存碎片問題就得到了解決。存分區(qū)。顯然,
5、采用這樣的內(nèi)存管理算法,上面的內(nèi)存碎片問題就得到了解決。圖圖 F12.1F12.1 內(nèi)存分區(qū)內(nèi)存分區(qū)FigureFigure 12.112.1圖圖 F12.2F12.2 多個內(nèi)存分區(qū)多個內(nèi)存分區(qū)FigureFigure 12.212.27.07.012.0 內(nèi)存控制塊內(nèi)存控制塊為了便于內(nèi)存的管理,在為了便于內(nèi)存的管理,在 C/OS-IIC/OS-II 中使用內(nèi)存控制塊(中使用內(nèi)存控制塊(memorymemory controlcontrol blocksblocks)的數(shù)據(jù)結(jié)構(gòu))的數(shù)據(jù)結(jié)構(gòu)來跟蹤每一個內(nèi)存分區(qū),系統(tǒng)中的每個內(nèi)存分區(qū)都有它自己的內(nèi)存控制塊。程序清單來跟蹤每一個內(nèi)存分區(qū),系統(tǒng)中的每
6、個內(nèi)存分區(qū)都有它自己的內(nèi)存控制塊。程序清單 L12.1L12.1 是是內(nèi)存控制塊的定義。內(nèi)存控制塊的定義。程序清單程序清單 L12.1L12.1 內(nèi)存控制塊的數(shù)據(jù)結(jié)構(gòu)內(nèi)存控制塊的數(shù)據(jù)結(jié)構(gòu)typedeftypedef structstruct voidvoid *OSMemAddr;*OSMemAddr; voidvoid *OSMemFreeList;*OSMemFreeList; INT32UINT32U OSMemBlkSize;OSMemBlkSize; INT32UINT32U OSMemNBlks;OSMemNBlks; INT32UINT32U OSMemNFree;OSMemNF
7、ree; OS_MEM;OS_MEM;.OSMemAddr.OSMemAddr 是指向內(nèi)存分區(qū)起始地址的指針。它在建立內(nèi)存分區(qū)是指向內(nèi)存分區(qū)起始地址的指針。它在建立內(nèi)存分區(qū) 見見 12.112.1 節(jié),建立一個內(nèi)存分節(jié),建立一個內(nèi)存分區(qū),區(qū),OSMemCreate()OSMemCreate()時被初始化,在此之后就不能更改了。時被初始化,在此之后就不能更改了。.OSMemFreeList.OSMemFreeList 是指向下一個空閑內(nèi)存控制塊或者下一個空閑的內(nèi)存塊的指針,具體含義要根是指向下一個空閑內(nèi)存控制塊或者下一個空閑的內(nèi)存塊的指針,具體含義要根據(jù)該內(nèi)存分區(qū)是否已經(jīng)建立來決定據(jù)該內(nèi)存分區(qū)是
8、否已經(jīng)建立來決定 見見 12.112.1 節(jié)節(jié) 。.OSMemBlkSize.OSMemBlkSize 是內(nèi)存分區(qū)中內(nèi)存塊的大小,是用戶建立該內(nèi)存分區(qū)時指定的是內(nèi)存分區(qū)中內(nèi)存塊的大小,是用戶建立該內(nèi)存分區(qū)時指定的 見見 12.112.1 節(jié)節(jié) 。.OSMemNBlks.OSMemNBlks 是內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)量,也是用戶建立該內(nèi)存分區(qū)時指定的是內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)量,也是用戶建立該內(nèi)存分區(qū)時指定的 見見 12.112.1 節(jié)節(jié) 。.OSMemNFree.OSMemNFree 是內(nèi)存分區(qū)中當前可以得空閑內(nèi)存塊數(shù)量。是內(nèi)存分區(qū)中當前可以得空閑內(nèi)存塊數(shù)量。如果要在如果要在 C/OS-IIC/
9、OS-II 中使用內(nèi)存管理,需要在中使用內(nèi)存管理,需要在文件中將開關量文件中將開關量 OS_MEM_ENOS_MEM_EN 設置為設置為 1 1。這樣。這樣C/OS-IIC/OS-II 在啟動時就會對內(nèi)存管理器進行初始化在啟動時就會對內(nèi)存管理器進行初始化 由由 OSInit()OSInit()調(diào)用調(diào)用 OSMemInit()OSMemInit()實現(xiàn)實現(xiàn) 。該初。該初始化主要建立一個圖始化主要建立一個圖 F12.3F12.3 所示的內(nèi)存控制塊鏈表,其中的常數(shù)所示的內(nèi)存控制塊鏈表,其中的常數(shù) OS_MAX_MEM_PARTOS_MAX_MEM_PART(見文件)(見文件)定義了最大的內(nèi)存分區(qū)數(shù),
10、該常數(shù)值至少應為定義了最大的內(nèi)存分區(qū)數(shù),該常數(shù)值至少應為 2 2。圖圖 F12.3F12.3 空閑內(nèi)存控制塊鏈表空閑內(nèi)存控制塊鏈表FigureFigure 12.312.37.17.1建立一個內(nèi)存分區(qū),建立一個內(nèi)存分區(qū),OSMemCreate()OSMemCreate()在使用一個內(nèi)存分區(qū)之前,必須先建立該內(nèi)存分區(qū)。這個操作可以通過調(diào)用在使用一個內(nèi)存分區(qū)之前,必須先建立該內(nèi)存分區(qū)。這個操作可以通過調(diào)用 OSMemCreate()OSMemCreate()函函數(shù)來完成。程序清單數(shù)來完成。程序清單 L12.2L12.2 說明了如何建立一個含有說明了如何建立一個含有 100100 個內(nèi)存塊、每個內(nèi)存
11、塊個內(nèi)存塊、每個內(nèi)存塊 3232 字節(jié)的內(nèi)字節(jié)的內(nèi)存分區(qū)。存分區(qū)。程序清單程序清單 L12.2L12.2 建立一個內(nèi)存分區(qū)建立一個內(nèi)存分區(qū)OS_MEMOS_MEM *CommTxBuf;*CommTxBuf;INT8UINT8U CommTxPart10032;CommTxPart10032;voidvoid mainmain (void)(void) INT8UINT8U err;err; OSInit();OSInit(); . . . . CommTxBufCommTxBuf = = OSMemCreate(CommTxPart,OSMemCreate(CommTxPart, 100,1
12、00, 32,32, &err);&err); . . . . OSStart();OSStart(); 程序清單程序清單 L12.3L12.3 是是 OSMemCreate()OSMemCreate()函數(shù)的源代碼。該函數(shù)共有函數(shù)的源代碼。該函數(shù)共有 4 4 個參數(shù):內(nèi)存分區(qū)的起始地址、個參數(shù):內(nèi)存分區(qū)的起始地址、分區(qū)內(nèi)的內(nèi)存塊總塊數(shù)、每個內(nèi)存塊的字節(jié)數(shù)和一個指向錯誤信息代碼的指針。如果分區(qū)內(nèi)的內(nèi)存塊總塊數(shù)、每個內(nèi)存塊的字節(jié)數(shù)和一個指向錯誤信息代碼的指針。如果OSMemCreate()OSMemCreate()操作失敗,它將返回一個操作失敗,它將返回一個 NULLNULL 指
13、針。否則,它將返回一個指向內(nèi)存控制塊的指指針。否則,它將返回一個指向內(nèi)存控制塊的指針。對內(nèi)存管理的其它操作,象針。對內(nèi)存管理的其它操作,象 OSMemGet()OSMemGet(),OSMemPut()OSMemPut(),OSMemQuery()OSMemQuery()函數(shù)等,都要通過該函數(shù)等,都要通過該指針進行。指針進行。每個內(nèi)存分區(qū)必須含有至少兩個內(nèi)存塊每個內(nèi)存分區(qū)必須含有至少兩個內(nèi)存塊L12.3(1)L12.3(1),每個內(nèi)存塊至少為一個指針的大小,因為,每個內(nèi)存塊至少為一個指針的大小,因為同一分區(qū)中的所有空閑內(nèi)存塊是由指針串聯(lián)起來的同一分區(qū)中的所有空閑內(nèi)存塊是由指針串聯(lián)起來的L12.
14、3(2)L12.3(2)。接著,。接著,OSMemCreate()OSMemCreate()從系統(tǒng)從系統(tǒng)中的空閑內(nèi)存控制塊中取得一個內(nèi)存控制塊中的空閑內(nèi)存控制塊中取得一個內(nèi)存控制塊L12.3(3)L12.3(3),該內(nèi)存控制塊包含相應內(nèi)存分區(qū)的運,該內(nèi)存控制塊包含相應內(nèi)存分區(qū)的運行信息。行信息。OSMemCreate()OSMemCreate()必須在有空閑內(nèi)存控制塊可用的情況下才能建立一個內(nèi)存分區(qū)必須在有空閑內(nèi)存控制塊可用的情況下才能建立一個內(nèi)存分區(qū)L12.3(4)L12.3(4)。在上述條件均得到滿足時,所要建立的內(nèi)存分區(qū)內(nèi)的所有內(nèi)存塊被鏈接成一個單。在上述條件均得到滿足時,所要建立的內(nèi)存
15、分區(qū)內(nèi)的所有內(nèi)存塊被鏈接成一個單向的鏈表向的鏈表L12.3(5)L12.3(5)。然后,在對應的內(nèi)存控制塊中填寫相應的信息。然后,在對應的內(nèi)存控制塊中填寫相應的信息L12.3(6)L12.3(6)。完成上述各。完成上述各動作后,動作后,OSMemCreate()OSMemCreate()返回指向該內(nèi)存塊的指針。該指針在以后對內(nèi)存塊的操作中使用返回指向該內(nèi)存塊的指針。該指針在以后對內(nèi)存塊的操作中使用L12.3(6)L12.3(6)。程序清單程序清單 L12.3L12.3 OSMemCreate()OSMemCreate()OS_MEMOS_MEM *OSMemCreate*OSMemCreate
16、 (void(void *addr,*addr, INT32UINT32U nblks,nblks, INT32UINT32U blksize,blksize, INT8UINT8U *err)*err) OS_MEMOS_MEM *pmem;*pmem; INT8UINT8U *pblk;*pblk; voidvoid *plink;*plink; INT32UINT32U i;i; ifif (nblks(nblks 2)2) (1)(1) *err*err = = OS_MEM_INVALID_BLKS;OS_MEM_INVALID_BLKS; returnreturn (OS_MEM(
17、OS_MEM *)0);*)0); ifif (blksize(blksize OSMemFreeList;*)OSMemFreeList-OSMemFreeList; OS_EXIT_CRITICAL();OS_EXIT_CRITICAL(); ifif (pmem(pmem = (OS_MEM(OS_MEM *)0)*)0) (4)(4) *err*err = = OS_MEM_INVALID_PART;OS_MEM_INVALID_PART; returnreturn (OS_MEM(OS_MEM *)0);*)0); plinkplink = = (void(void *)addr;*
18、)addr; (5)(5) pblkpblk = = (INT8U(INT8U *)addr*)addr + + blksize;blksize; forfor (i(i = = 0;0; i i OSMemAddrpmem-OSMemAddr = = addr;addr; (6)(6) pmem-OSMemFreeListpmem-OSMemFreeList = = addr;addr; pmem-OSMemNFreepmem-OSMemNFree = = nblks;nblks; pmem-OSMemNBlkspmem-OSMemNBlks = = nblks;nblks; pmem-OS
19、MemBlkSizepmem-OSMemBlkSize = = blksize;blksize; OS_EXIT_CRITICAL();OS_EXIT_CRITICAL(); *err*err = = OS_NO_ERR;OS_NO_ERR; returnreturn (pmem);(pmem); (7)(7) 圖圖 F12.4F12.4 是是 OSMemCreate()OSMemCreate()函數(shù)完成后,內(nèi)存控制塊及對應的內(nèi)存分區(qū)和分區(qū)內(nèi)的內(nèi)存塊之間函數(shù)完成后,內(nèi)存控制塊及對應的內(nèi)存分區(qū)和分區(qū)內(nèi)的內(nèi)存塊之間的關系。在程序運行期間,經(jīng)過多次的內(nèi)存分配和釋放后,同一分區(qū)內(nèi)的各內(nèi)存塊之間的鏈接的
20、關系。在程序運行期間,經(jīng)過多次的內(nèi)存分配和釋放后,同一分區(qū)內(nèi)的各內(nèi)存塊之間的鏈接順序會發(fā)生很大的變化。順序會發(fā)生很大的變化。圖圖 F12.4F12.4 OSMemCreate()OSMemCreate()FigureFigure7.27.212.212.2 分配一個內(nèi)存塊,分配一個內(nèi)存塊,OSMemGet()OSMemGet()應用程序可以調(diào)用應用程序可以調(diào)用 OSMemGet()OSMemGet()函數(shù)從已經(jīng)建立的內(nèi)存分區(qū)中申請一個內(nèi)存塊。該函數(shù)的唯一參函數(shù)從已經(jīng)建立的內(nèi)存分區(qū)中申請一個內(nèi)存塊。該函數(shù)的唯一參數(shù)是指向特定內(nèi)存分區(qū)的指針,該指針在建立內(nèi)存分區(qū)時,由數(shù)是指向特定內(nèi)存分區(qū)的指針,該
21、指針在建立內(nèi)存分區(qū)時,由 OSMemCreate()OSMemCreate()函數(shù)返回。顯然,函數(shù)返回。顯然,應用程序必須知道內(nèi)存塊的大小,并且在使用時不能超過該容量。例如,如果一個內(nèi)存分區(qū)內(nèi)應用程序必須知道內(nèi)存塊的大小,并且在使用時不能超過該容量。例如,如果一個內(nèi)存分區(qū)內(nèi)的內(nèi)存塊為的內(nèi)存塊為 3232 字節(jié),那么,應用程序最多只能使用該內(nèi)存塊中的字節(jié),那么,應用程序最多只能使用該內(nèi)存塊中的 3232 字節(jié)。當應用程序不再使字節(jié)。當應用程序不再使用這個內(nèi)存塊后,必須及時把它釋放,重新放入相應的內(nèi)存分區(qū)中用這個內(nèi)存塊后,必須及時把它釋放,重新放入相應的內(nèi)存分區(qū)中 見見 12.0312.03 節(jié),
22、釋放一個內(nèi)節(jié),釋放一個內(nèi)存塊,存塊,OSMemPut()OSMemPut()。程序清單程序清單 L12.4L12.4 是是 OSMemGet()OSMemGet()函數(shù)的源代碼。參數(shù)中的指針函數(shù)的源代碼。參數(shù)中的指針 pmempmem 指向用戶希望從其中分配內(nèi)指向用戶希望從其中分配內(nèi)存塊的內(nèi)存分區(qū)存塊的內(nèi)存分區(qū)L12.4(1)L12.4(1)。OSMemGet()OSMemGet()首先檢查內(nèi)存分區(qū)中是否有空閑的內(nèi)存塊首先檢查內(nèi)存分區(qū)中是否有空閑的內(nèi)存塊L12.4(2)L12.4(2)。如果有,從空閑內(nèi)存塊鏈表中刪除第一個內(nèi)存塊如果有,從空閑內(nèi)存塊鏈表中刪除第一個內(nèi)存塊L12.4(3)L12.
23、4(3),并對空閑內(nèi)存塊鏈表作相應的修,并對空閑內(nèi)存塊鏈表作相應的修改改 L12.4(4)L12.4(4)。這包括將鏈表頭指針后移一個元素和空閑內(nèi)存塊數(shù)減。這包括將鏈表頭指針后移一個元素和空閑內(nèi)存塊數(shù)減 1L12.4(5)1L12.4(5)。最后,返。最后,返回指向被分配內(nèi)存塊的指針回指向被分配內(nèi)存塊的指針L12.4(6)L12.4(6)。程序清單程序清單 L12.4L12.4 OSMemGet()OSMemGet()voidvoid *OSMemGet*OSMemGet (OS_MEM(OS_MEM *pmem,*pmem, INT8UINT8U *err)*err) (1)(1) void
24、void *pblk;*pblk; OS_ENTER_CRITICAL();OS_ENTER_CRITICAL(); ifif (pmem-OSMemNFree(pmem-OSMemNFree 0)0) (2)(2) pblkpblk = = pmem-OSMemFreeList;pmem-OSMemFreeList; (3)(3) pmem-OSMemFreeListpmem-OSMemFreeList = = *(void*(void *)pblk;*)pblk; (4)(4) pmem-OSMemNFree-;pmem-OSMemNFree-; (5)(5) OS_EXIT_CRITIC
25、AL();OS_EXIT_CRITICAL(); *err*err = = OS_NO_ERR;OS_NO_ERR; returnreturn (pblk);(pblk); (6)(6) elseelse OS_EXIT_CRITICAL();OS_EXIT_CRITICAL(); *err*err = = OS_MEM_NO_FREE_BLKS;OS_MEM_NO_FREE_BLKS; returnreturn (void(void *)0);*)0); 值得注意的是,用戶可以在中斷服務子程序中調(diào)用值得注意的是,用戶可以在中斷服務子程序中調(diào)用 OSMemGet()OSMemGet(),因為在
26、暫時沒有內(nèi)存塊可用的,因為在暫時沒有內(nèi)存塊可用的情況下,情況下,OSMemGet()OSMemGet()不會等待,而是馬上返回不會等待,而是馬上返回 NULLNULL 指針。指針。7.37.312.312.3 釋放一個內(nèi)存塊,釋放一個內(nèi)存塊,OSMemPut()OSMemPut()當用戶應用程序不再使用一個內(nèi)存塊時,必須及時地把它釋放并放回到相應的內(nèi)存分區(qū)中。這當用戶應用程序不再使用一個內(nèi)存塊時,必須及時地把它釋放并放回到相應的內(nèi)存分區(qū)中。這個操作由個操作由 OSMemPut()OSMemPut()函數(shù)完成。必須注意的是,函數(shù)完成。必須注意的是,OSMemPut()OSMemPut()并不知道
27、一個內(nèi)存塊是屬于哪個內(nèi)并不知道一個內(nèi)存塊是屬于哪個內(nèi)存分區(qū)的。例如,用戶任務從一個包含存分區(qū)的。例如,用戶任務從一個包含 3232 字節(jié)內(nèi)存塊的分區(qū)中分配了一個內(nèi)存塊,用完后,字節(jié)內(nèi)存塊的分區(qū)中分配了一個內(nèi)存塊,用完后,把它返還給了一個包含把它返還給了一個包含 120120 字節(jié)內(nèi)存塊的內(nèi)存分區(qū)。當用戶應用程序下一次申請字節(jié)內(nèi)存塊的內(nèi)存分區(qū)。當用戶應用程序下一次申請 120120 字節(jié)分區(qū)字節(jié)分區(qū)中的一個內(nèi)存塊時,它會只得到中的一個內(nèi)存塊時,它會只得到 3232 字節(jié)的可用空間,其它字節(jié)的可用空間,其它 8888 字節(jié)屬于其它的任務,這就有可字節(jié)屬于其它的任務,這就有可能使系統(tǒng)崩潰。能使系統(tǒng)崩
28、潰。程序清單程序清單 L12.5L12.5 是是 OSMemPut()OSMemPut()函數(shù)的源代碼。它的第一個參數(shù)函數(shù)的源代碼。它的第一個參數(shù) pmempmem 是指向內(nèi)存控制塊的指針,是指向內(nèi)存控制塊的指針,也即內(nèi)存塊屬于的內(nèi)存分區(qū)也即內(nèi)存塊屬于的內(nèi)存分區(qū)L12.5(1)L12.5(1)。OSMemPut()OSMemPut()首先檢查內(nèi)存分區(qū)是否已滿首先檢查內(nèi)存分區(qū)是否已滿L12.5(2)L12.5(2)。如果已滿,說明系統(tǒng)在分配和釋放內(nèi)存時出現(xiàn)了錯誤。如果未滿,要釋放的內(nèi)存塊被插入到該如果已滿,說明系統(tǒng)在分配和釋放內(nèi)存時出現(xiàn)了錯誤。如果未滿,要釋放的內(nèi)存塊被插入到該分區(qū)的空閑內(nèi)存塊鏈
29、表中分區(qū)的空閑內(nèi)存塊鏈表中L12.5(3)L12.5(3)。最后,將分區(qū)中空閑內(nèi)存塊總數(shù)加。最后,將分區(qū)中空閑內(nèi)存塊總數(shù)加 1L12.5(4)1L12.5(4)。程序清單程序清單 L12.5L12.5 OSMemPut()OSMemPut()INT8UINT8U OSMemPutOSMemPut (OS_MEM(OS_MEM *pmem,*pmem, voidvoid *pblk)*pblk) (1)(1) OS_ENTER_CRITICAL();OS_ENTER_CRITICAL(); ifif (pmem-OSMemNFree(pmem-OSMemNFree = pmem-OSMemNBl
30、ks)pmem-OSMemNBlks) (2)(2) OS_EXIT_CRITICAL();OS_EXIT_CRITICAL(); returnreturn (OS_MEM_FULL);(OS_MEM_FULL); *(void*(void *)pblk*)pblk = = pmem-OSMemFreeList;pmem-OSMemFreeList; (3)(3) pmem-OSMemFreeListpmem-OSMemFreeList = = pblk;pblk; pmem-OSMemNFree+;pmem-OSMemNFree+; (4)(4) OS_EXIT_CRITICAL();OS_
31、EXIT_CRITICAL(); returnreturn (OS_NO_ERR);(OS_NO_ERR); 7.47.412.412.4 查詢一個內(nèi)存分區(qū)的狀態(tài),查詢一個內(nèi)存分區(qū)的狀態(tài),OSMemQuery()OSMemQuery()在在 C/OS-IIC/OS-II 中,可以使用中,可以使用 OSMemQuery()OSMemQuery()函數(shù)來查詢一個特定內(nèi)存分區(qū)的有關消息。通過該函函數(shù)來查詢一個特定內(nèi)存分區(qū)的有關消息。通過該函數(shù)可以知道特定內(nèi)存分區(qū)中內(nèi)存塊的大小、可用內(nèi)存塊數(shù)和正在使用的內(nèi)存塊數(shù)等信息。所有數(shù)可以知道特定內(nèi)存分區(qū)中內(nèi)存塊的大小、可用內(nèi)存塊數(shù)和正在使用的內(nèi)存塊數(shù)等信息。所
32、有這些信息都放在一個叫這些信息都放在一個叫 OS_MEM_DATAOS_MEM_DATA 的數(shù)據(jù)結(jié)構(gòu)中,如程序清單的數(shù)據(jù)結(jié)構(gòu)中,如程序清單 L12.6L12.6。程序清單程序清單 L12.6L12.6 OS_MEM_DATAOS_MEM_DATA數(shù)據(jù)結(jié)構(gòu)數(shù)據(jù)結(jié)構(gòu)typedeftypedef structstruct voidvoid *OSAddr;*OSAddr; /*/* 指向內(nèi)存分區(qū)首地址的指針指向內(nèi)存分區(qū)首地址的指針 */*/ voidvoid *OSFreeList;*OSFreeList; /*/* 指向空閑內(nèi)存塊鏈表首地址的指針指向空閑內(nèi)存塊鏈表首地址的指針 */*/ INT32
33、UINT32U OSBlkSize;OSBlkSize; /*/* 每個內(nèi)存塊所含的字節(jié)數(shù)每個內(nèi)存塊所含的字節(jié)數(shù) */*/ INT32UINT32U OSNBlks;OSNBlks; /*/* 內(nèi)存分區(qū)總的內(nèi)存塊數(shù)內(nèi)存分區(qū)總的內(nèi)存塊數(shù) */*/ INT32UINT32U OSNFree;OSNFree; /*/* 空閑內(nèi)存塊總數(shù)空閑內(nèi)存塊總數(shù) */*/ INT32UINT32U OSNUsed;OSNUsed; /*/* 正在使用的內(nèi)存塊總數(shù)正在使用的內(nèi)存塊總數(shù) */*/ OS_MEM_DATA;OS_MEM_DATA;程序清單程序清單 L12.7L12.7 是是 OSMemQuery()OS
34、MemQuery()函數(shù)的源代碼,它將指定內(nèi)存分區(qū)的信息復制到函數(shù)的源代碼,它將指定內(nèi)存分區(qū)的信息復制到 OS_MEM_DATAOS_MEM_DATA定義的變量的對應域中。在此之前,代碼首先禁止了外部中斷,防止復制過程中某些變量值被定義的變量的對應域中。在此之前,代碼首先禁止了外部中斷,防止復制過程中某些變量值被修改修改L12.7(1)L12.7(1)。由于正在使用的內(nèi)存塊數(shù)是由。由于正在使用的內(nèi)存塊數(shù)是由 OS_MEM_DATAOS_MEM_DATA 中的局部變量計算得到的,所以,中的局部變量計算得到的,所以,可以放在(可以放在(criticalcritical sectionsection
35、 中斷屏蔽)的外面。中斷屏蔽)的外面。程序清單程序清單 L12.7L12.7 OSMemQuery()OSMemQuery()INT8UINT8U OSMemQueryOSMemQuery (OS_MEM(OS_MEM *pmem,*pmem, OS_MEM_DATAOS_MEM_DATA *pdata)*pdata) OS_ENTER_CRITICAL();OS_ENTER_CRITICAL(); pdata-OSAddrpdata-OSAddr = = pmem-OSMemAddr;pmem-OSMemAddr; (1)(1) pdata-OSFreeListpdata-OSFreeLis
36、t = = pmem-OSMemFreeList;pmem-OSMemFreeList; pdata-OSBlkSizepdata-OSBlkSize = = pmem-OSMemBlkSize;pmem-OSMemBlkSize; pdata-OSNBlkspdata-OSNBlks = = pmem-OSMemNBlks;pmem-OSMemNBlks; pdata-OSNFreepdata-OSNFree = = pmem-OSMemNFree;pmem-OSMemNFree; OS_EXIT_CRITICAL();OS_EXIT_CRITICAL(); pdata-OSNUsedpda
37、ta-OSNUsed = = pdata-OSNBlkspdata-OSNBlks - - pdata-OSNFree;pdata-OSNFree; (2)(2) returnreturn (OS_NO_ERR);(OS_NO_ERR); 7.57.512.512.5 UsingUsing MemoryMemory PartitionsPartitions圖圖 F12.5F12.5 是一個演示如何使用是一個演示如何使用 C/OS-IIC/OS-II 中的動態(tài)分配內(nèi)存功能,以及利用它進行消息傳遞中的動態(tài)分配內(nèi)存功能,以及利用它進行消息傳遞 見見第第 1111 章章 的例子。程序清單的例子。程序清
38、單 L12.8L12.8 是這個例子中兩個任務的示意代碼,其中一些重要代碼的標是這個例子中兩個任務的示意代碼,其中一些重要代碼的標號和圖號和圖 F12.5F12.5 中括號內(nèi)用數(shù)字標識的動作是相對應的。中括號內(nèi)用數(shù)字標識的動作是相對應的。第一個任務讀取并檢查模擬輸入量的值(如氣壓、溫度、電壓等),如果其超過了一定的閾值,第一個任務讀取并檢查模擬輸入量的值(如氣壓、溫度、電壓等),如果其超過了一定的閾值,就向第二個任務發(fā)送一個消息。該消息中含有時間信息、出錯的通道號和錯誤代碼等可以想象就向第二個任務發(fā)送一個消息。該消息中含有時間信息、出錯的通道號和錯誤代碼等可以想象的任何可能的信息。的任何可能的
39、信息。錯誤處理程序是該例子的中心。任何任務、中斷服務子程序都可以向該任務發(fā)送出錯消息。錯錯誤處理程序是該例子的中心。任何任務、中斷服務子程序都可以向該任務發(fā)送出錯消息。錯誤處理程序則負責在顯示設備上顯示出錯信息,在磁盤上登記出錯記錄,或者啟動另一個任務誤處理程序則負責在顯示設備上顯示出錯信息,在磁盤上登記出錯記錄,或者啟動另一個任務對錯誤進行糾正等。對錯誤進行糾正等。圖圖 F12.5F12.5 使用動態(tài)內(nèi)存分配使用動態(tài)內(nèi)存分配FigureFigure 12.512.5程序清單程序清單 L12.8L12.8 內(nèi)存分配的例子內(nèi)存分配的例子掃描模擬量的輸入和報告出錯掃描模擬量的輸入和報告出錯Anal
40、ogInputTask()AnalogInputTask() forfor (;)(;) forfor ( (所有的模擬量都有輸入所有的模擬量都有輸入) ) 讀入模擬量輸入值讀入模擬量輸入值; ; (1)(1) ifif ( (模擬量超過閾值模擬量超過閾值) ) 得到一個內(nèi)存塊得到一個內(nèi)存塊; ; (2)(2) 得到當前系統(tǒng)時間得到當前系統(tǒng)時間 ( (以時鐘節(jié)拍為單位以時鐘節(jié)拍為單位);); (3)(3) 將下列各項存入內(nèi)存塊將下列各項存入內(nèi)存塊: : (4)(4) 系統(tǒng)時間系統(tǒng)時間 ( (時間戳時間戳);); 超過閾值的通道號超過閾值的通道號; ; 錯誤代碼錯誤代碼; ; 錯誤等級錯誤等級;
41、 ; 等等. . 向錯誤隊列發(fā)送錯誤消息向錯誤隊列發(fā)送錯誤消息; ; (5)(5) ( (一個指向包含上述各項的內(nèi)存塊的指針一個指向包含上述各項的內(nèi)存塊的指針) ) 延時任務延時任務, ,直到要再次對模擬量進行采樣時為止直到要再次對模擬量進行采樣時為止; ; ErrorHandlerTask()ErrorHandlerTask() forfor (;)(;) 等待錯誤隊列的消息等待錯誤隊列的消息; ; (6)(6) ( (得到指向包含有關錯誤數(shù)據(jù)的內(nèi)存塊的指針得到指向包含有關錯誤數(shù)據(jù)的內(nèi)存塊的指針) ) 讀入消息讀入消息, ,并根據(jù)消息的內(nèi)容執(zhí)行相應的操作并根據(jù)消息的內(nèi)容執(zhí)行相應的操作; ;
42、(7)(7) 將內(nèi)存塊放回到相應的內(nèi)存分區(qū)中將內(nèi)存塊放回到相應的內(nèi)存分區(qū)中; ; (8)(8) 7.67.612.612.6 等待一個內(nèi)存塊等待一個內(nèi)存塊有時候,在內(nèi)存分區(qū)暫時沒有可用的空閑內(nèi)存塊的情況下,讓一個申請內(nèi)存塊的任務等待也是有時候,在內(nèi)存分區(qū)暫時沒有可用的空閑內(nèi)存塊的情況下,讓一個申請內(nèi)存塊的任務等待也是有用的。但是,有用的。但是,C/OS-IIC/OS-II 本身在內(nèi)存管理上并不支持這項功能。如果確實需要,則可以通過為本身在內(nèi)存管理上并不支持這項功能。如果確實需要,則可以通過為特定內(nèi)存分區(qū)增加信號量的方法,實現(xiàn)這種功能(見特定內(nèi)存分區(qū)增加信號量的方法,實現(xiàn)這種功能(見 7.057
43、.05 節(jié),信號量)。應用程序為了申請節(jié),信號量)。應用程序為了申請分配內(nèi)存塊,首先要得到一個相應的信號量,然后才能調(diào)用分配內(nèi)存塊,首先要得到一個相應的信號量,然后才能調(diào)用 OSMemGet()OSMemGet()函數(shù)。整個過程見程序函數(shù)。整個過程見程序清單清單 L12.9L12.9。程序代碼首先定義了程序中使用到的各個變量程序代碼首先定義了程序中使用到的各個變量L12.9(1)L12.9(1)。該例中,直接使用數(shù)字定義了各個。該例中,直接使用數(shù)字定義了各個變量的大小,實際應用中,建議將這些數(shù)字定義成常數(shù)。在系統(tǒng)復位時,變量的大小,實際應用中,建議將這些數(shù)字定義成常數(shù)。在系統(tǒng)復位時,C/OS-
44、IIC/OS-II 調(diào)用調(diào)用OSInit()OSInit()進行系統(tǒng)初始化進行系統(tǒng)初始化L12.9(2)L12.9(2),然后用內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)來初始化一個信號量,然后用內(nèi)存分區(qū)中總的內(nèi)存塊數(shù)來初始化一個信號量L12.9(3)L12.9(3),緊接著建立內(nèi)存分區(qū),緊接著建立內(nèi)存分區(qū)L12.9(4)L12.9(4)和相應的要訪問該分區(qū)的任務和相應的要訪問該分區(qū)的任務L12.9(5)L12.9(5)。當然,。當然,到此為止,我們對如何增加其它的任務也已經(jīng)很清楚了。顯然,如果系統(tǒng)中只有一個任務使用到此為止,我們對如何增加其它的任務也已經(jīng)很清楚了。顯然,如果系統(tǒng)中只有一個任務使用動態(tài)內(nèi)存塊,就沒
45、有必要使用信號量了。這種情況不需要保證內(nèi)存資源的互斥。事實上,除非動態(tài)內(nèi)存塊,就沒有必要使用信號量了。這種情況不需要保證內(nèi)存資源的互斥。事實上,除非我們要實現(xiàn)多任務共享內(nèi)存,否則連內(nèi)存分區(qū)都不需要。多任務執(zhí)行從我們要實現(xiàn)多任務共享內(nèi)存,否則連內(nèi)存分區(qū)都不需要。多任務執(zhí)行從 OSStart()OSStart()開始開始L12.9(6)L12.9(6)。當一個任務運行時,只有在信號量有效時。當一個任務運行時,只有在信號量有效時L12.9(7)L12.9(7),才有可能得到內(nèi)存塊,才有可能得到內(nèi)存塊L12.9(8)L12.9(8)。一旦信號量有效了,就可以申請內(nèi)存塊并使用它,而沒有必要對。一旦信號量
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 建立高效的財務業(yè)務運作模式
- 2025年全球及中國工業(yè)級4-芐氧基苯酚行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025年全球及中國石墨片保護膜行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025年全球及中國消費電子NFC天線行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025年全球及中國旅游廣告和營銷服務行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025-2030全球非侵入式血流動力學監(jiān)測解決方案行業(yè)調(diào)研及趨勢分析報告
- 2025年全球及中國光伏舟托行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025年全球及中國晶須碳納米管行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025年全球及中國溴化鈣粉行業(yè)頭部企業(yè)市場占有率及排名調(diào)研報告
- 2025-2030全球高壓鎳氫電池行業(yè)調(diào)研及趨勢分析報告
- 2024年全國職業(yè)院校技能大賽高職組(生產(chǎn)事故應急救援賽項)考試題庫(含答案)
- 2024年江蘇農(nóng)牧科技職業(yè)學院高職單招語文歷年參考題庫含答案解析
- 廣聯(lián)達智慧工地合同范例
- 老年上消化道出血急診診療專家共識2024
- 廣東省廣州黃埔區(qū)2023-2024學年八年級上學期期末物理試卷(含答案)
- 醫(yī)院護理10s管理
- 人教版一年級下冊數(shù)學第五單元認識人民幣練習
- 學校安全工作計劃及行事歷
- 《GMP基礎知識培訓》課件
- 2025屆江蘇省無錫市天一中學高一上數(shù)學期末質(zhì)量檢測試題含解析
- 數(shù)學家華羅庚課件
評論
0/150
提交評論