嵌入式系統(tǒng)中的CACHE問(wèn)題
2 問(wèn)題的分析 要解釋這個(gè)問(wèn)題,首先要了解CACHE的工作模式。CACHE的基本工作模式有兩種:write-through模式和 copyback模式。在write-through模式下,所有的寫(xiě)操作都寫(xiě)入CACHE和RAM,保證了CACHE和RAM的一致。然而,每次對(duì)RAM都有寫(xiě)操作會(huì)使處理器的處理能力降低,并且占用總線(xiàn)帶寬。在copyback模式下,寫(xiě)操作只寫(xiě)入CACHE,不寫(xiě)入RAM,從而提高了處理器性能和總線(xiàn)帶寬。copyback模式下,CACHE中的內(nèi)容只有在需要的時(shí)候才寫(xiě)到RAM中。當(dāng)CACHE中無(wú)可用空間時(shí),一般使用最近最少使用算法(LRU)來(lái)決定哪一個(gè)CACHE項(xiàng)被替換。copyback模式提供了很高的系統(tǒng)性能,但是需要更多的一致性作保證。為了便于理解,給出一個(gè)使用了CACHE的系統(tǒng)的邏輯框圖,如圖1所示。 該系統(tǒng)中兩個(gè)地方會(huì)發(fā)生CACHE的不一致性: (1)數(shù)據(jù)CACHE / RAM 數(shù)據(jù)CACHE與RAM之間的問(wèn)題源于處理器和其他總線(xiàn)控制器對(duì)RAM的異步讀寫(xiě)訪(fǎng)問(wèn)。DMA設(shè)備和其他總線(xiàn)控制器對(duì)RAM的訪(fǎng)問(wèn)是引起CACHE一致性問(wèn)題的主要原因,這個(gè)問(wèn)題可以通過(guò)在程序中加入一些代碼來(lái)解決。 (2)共享CACHE LINE 當(dāng)一個(gè)CACHE LINE被兩個(gè)以上的線(xiàn)程共享時(shí),也會(huì)產(chǎn)生一致性問(wèn)題。當(dāng)某個(gè)線(xiàn)程使一個(gè)CACHE LINE無(wú)效時(shí),這個(gè)CACHE LINE中的一些項(xiàng)可能屬于另外一個(gè)線(xiàn)程。這個(gè)問(wèn)題也可以通過(guò)一定的方法來(lái)避免,只要在分配內(nèi)存時(shí)大小是CACHE LINE大小的整數(shù)倍即可。 在哈佛體系結(jié)構(gòu)、copyback模式和無(wú)軟件干預(yù)的前提下,最佳的保持一致性的方法就是使用具有總線(xiàn)監(jiān)聽(tīng)能力的硬件。將CACHE、RAM、DMA設(shè)備和其它所有的總線(xiàn)主控設(shè)備都連到一個(gè)物理總線(xiàn)上,以使CACHE可以對(duì)該總線(xiàn)上的總線(xiàn)交互過(guò)程進(jìn)行監(jiān)聽(tīng),CACHE將對(duì)總線(xiàn)上的地址周期和控制(讀/寫(xiě))比特監(jiān)聽(tīng),數(shù)據(jù)周期則被延遲到需要時(shí)才進(jìn)行。當(dāng)CACHE中的一項(xiàng)被一個(gè)異步操作修改時(shí),該CACHE項(xiàng)就會(huì)被標(biāo)為無(wú)效。如果處理器對(duì)一個(gè)已經(jīng)被標(biāo)為無(wú)效的CACHE項(xiàng)進(jìn)行訪(fǎng)問(wèn)時(shí),CACHE就會(huì)從RAM中重新載入有效數(shù)據(jù)。在copyback模式下,處理器對(duì)CACHE進(jìn)行寫(xiě)操作時(shí),RAM相應(yīng)地址中的內(nèi)容就變成過(guò)時(shí)。如果另外一個(gè)設(shè)備想訪(fǎng)問(wèn)RAM中的這部分內(nèi)容,CACHE就會(huì)搶占該訪(fǎng)問(wèn)周期,將有效的數(shù)據(jù)寫(xiě)入RAM。然后被搶占的訪(fǎng)問(wèn)周期重新開(kāi)始并將讀到RAM中的有效數(shù)據(jù)。但是,目前提供監(jiān)聽(tīng)能力的板子并不多。 3 解決的方法 根據(jù)上面的分析和討論,可見(jiàn)問(wèn)題正是由數(shù)據(jù)CACHE / RAM的不一致性引起的。雖然關(guān)掉CACHE就可以解決一致性的問(wèn)題,并且能夠減小程序開(kāi)發(fā)的復(fù)雜度。但是一個(gè)高性能的系統(tǒng)是需要CACHE的,關(guān)掉CACHE會(huì)大大降低系統(tǒng)的性能。因此,本文僅討論在程序中加入代碼來(lái)克服一致性問(wèn)題的方法。 可以采用以下幾種加入代碼的方法來(lái)解決一致性的問(wèn)題本文使用WIND RIVER公司的嵌入式實(shí)時(shí)多任務(wù)操作系統(tǒng)VxWORKS,下面的函數(shù)都是VxWORKS提供的: (1)對(duì)于時(shí)間上不是那么關(guān)鍵的程序段,可以先用下面的代碼維護(hù)數(shù)據(jù)CACHE的一致性。 cacheInvalidate DATA_CACHE address bytes / 輸入緩沖區(qū)/ ... cacheFlush DATA_CACHE address bytes /輸出緩沖區(qū)/ (2)對(duì)于時(shí)間上比較關(guān)鍵的程序段采用如下原則:在每次使用輸出緩沖區(qū)前將其更新;在每次使用輸入緩沖區(qū)前使其無(wú)效。 將緩沖區(qū)標(biāo)示為“non-cacheable”可以防止一致性問(wèn)題,這需要MMU支持。在分配緩沖區(qū)時(shí),將其標(biāo)示為“non-cacheable”即可。然而,動(dòng)態(tài)緩沖區(qū)在釋放時(shí)要標(biāo)為“cacheable”,否則內(nèi)存總會(huì)產(chǎn)生大量的緩沖區(qū)碎片。 下面給出一個(gè)高性能的驅(qū)動(dòng)程序例子,它把更新/無(wú)效的概念進(jìn)行了擴(kuò)展。不是對(duì)整個(gè)CACHE系統(tǒng),而是對(duì)每一個(gè)緩沖區(qū)都這樣做。即通過(guò)分配對(duì)CACHE安全的緩沖區(qū),在一個(gè)緩沖區(qū)的基礎(chǔ)上操作,從而防止了不需要的更新/無(wú)效操作。在這個(gè)例子中使用了CACHE庫(kù)中的函數(shù)cacheDMAMalloc ,宏CACHE_DMA_INVALIDATE和CACHE_DMA_FLUSH實(shí)現(xiàn)一致性。在第4行調(diào)用函數(shù)cacheDMAMalloc 后,如果指針?lè)祷貫榉强眨瑒t說(shuō)明分配到了一塊對(duì)于一致性問(wèn)題來(lái)說(shuō)是安全的緩沖區(qū)。 第7行驅(qū)動(dòng)程序在緩沖區(qū)中寫(xiě)入要傳給外部設(shè)備的數(shù)據(jù),在第9行準(zhǔn)備傳給外設(shè)之前,驅(qū)動(dòng)程序必須更新數(shù)據(jù)CACHE以保證要傳的數(shù)據(jù)是在內(nèi)存中,而不是在CACHE中。 當(dāng)驅(qū)動(dòng)程序準(zhǔn)備讀外設(shè)傳給內(nèi)存的數(shù)據(jù),在第13行驅(qū)動(dòng)程序處理這些數(shù)據(jù)之前,必須使數(shù)據(jù)CACHE中對(duì)應(yīng)于輸入緩沖區(qū)的那部分無(wú)效以消除這些包含過(guò)時(shí)內(nèi)容的條目。之后,驅(qū)動(dòng)程序才能安全地處理從內(nèi)存中取來(lái)的輸入數(shù)據(jù)。 1: STATUS drvExample pBuf 2: void pBuf / 緩沖區(qū)指針 / 3: { /* 4: pBuf = cacheDMAMalloc BUF_SIZE 5: if pBuf == NULL 6: return ERROR /內(nèi)存分配失敗/ 7: /其它初始化代碼和向發(fā)送緩沖區(qū)填數(shù)據(jù)/ 8: CACHE_DMA_FLUSH pBuf BUF_SIZE 9: drvWrite pBuf /向外設(shè)發(fā)送數(shù)據(jù)/ 10: …… / 其它代碼 / 11: drvWait /等待外設(shè)來(lái)的數(shù)據(jù)/ 12: CACHE_DMA_INVALIDATE pBuf BUF_SIZE 13: / 處理外設(shè)來(lái)的數(shù)據(jù) / 14: cacheDMAFree pBuf /釋放內(nèi)存 / 15: return OK 16:}
linux操作系統(tǒng)文章專(zhuān)題:linux操作系統(tǒng)詳解(linux不再難懂)









評(píng)論