前文介紹了SylixOS中的塊設備驅動模型和I/O控制,本篇主要介紹SylixOS中的塊設備CACHE管理。因爲磁盤屬於低速設備,磁盤的讀寫速度遠遠低於CPU,因此爲了解決這種速度不匹配,SylixOS提供了對應塊設備的緩衝器。它是一個特殊的塊設備,與物理設備一一對應(多個邏輯分區共享一個CACHE),介於文件系統和磁盤之間,能夠極大地減小磁盤I/O的訪問率,同時提升系統性能。固然引入磁盤緩衝器的最大問題在於磁盤數據與緩衝數據的不一樣步性,這個問題能夠經過sync等函數調用來同步數據。緩存
SylixOS對塊設備CACHE管理的代碼在"libsylixos/SylixOS/fs/diskCache"目錄下,主要包含磁盤緩衝器的建立、刪除和同步操做,具體接口如程序清單 2-1所示。併發
程序清單 2-1 CACHE管理接口函數
LW_API ULONG API_DiskCacheCreate(PLW_BLK_DEV pblkdDisk, PVOID pvDiskCacheMem, size_t stMemSize, INT iMaxBurstSector, PLW_BLK_DEV *ppblkDiskCache); LW_API ULONG API_DiskCacheCreateEx(PLW_BLK_DEV pblkdDisk, PVOID pvDiskCacheMem, size_t stMemSize, INT iMaxRBurstSector, INT iMaxWBurstSector, PLW_BLK_DEV *ppblkDiskCache); LW_API ULONG API_DiskCacheCreateEx2(PLW_BLK_DEV pblkdDisk, PLW_DISKCACHE_ATTR pdcattrl, PLW_BLK_DEV *ppblkDiskCache); LW_API INT API_DiskCacheDelete(PLW_BLK_DEV pblkdDiskCache); LW_API INT API_DiskCacheSync(PLW_BLK_DEV pblkdDiskCache);
函數API_DiskCacheCreate是用來建立一個磁盤CACHE塊設備,pblkdDisk爲一個指向須要CACHE的塊設備結構的指針。該函數會調用到API_DiskCacheCreateEx函數,而API_DiskCacheCreateEx函數會繼續調用API_DiskCacheCreateEx2函數。三者在調用中對CACHE信息不斷封裝完善。性能
函數API_DiskCacheDelete用來刪除一個磁盤CACHE塊設備,在刪除磁盤以前首先要卸載卷。spa
函數API_DiskCacheSync用來磁盤高速緩衝控制器的回寫。線程
當使用函數API_DiskCacheCreate建立一個磁盤CACHE塊設備時,用戶須要提供磁盤CACHE的各類屬性信息,如CACHE緩衝區的內存起始地址、緩衝區大小、磁盤猝發讀寫的最大扇區數等。建立函數對屬性信息進行封裝,添加各類默認配置,最終調用API_DiskCacheCreateEx2函數進行具體的建立操做。用戶也可本身直接封裝信息描述結構體,並調用API_DiskCacheCreateEx2函數進行CACHE建立,封裝後的磁盤CACHE描述結構體如程序清單 2-2所示。指針
程序清單 2-2 CACHE描述信息結構體接口
typedef struct { PVOID DCATTR_pvCacheMem; /* 扇區緩存地址 */ size_t DCATTR_stMemSize; /* 扇區緩存大小 */ BOOL DCATTR_bCacheCoherence; /* 緩衝區須要 CACHE 一致性保障 */ INT DCATTR_iMaxRBurstSector; /* 磁盤猝發讀的最大扇區數 */ INT DCATTR_iMaxWBurstSector; /* 磁盤猝發寫的最大扇區數 */ INT DCATTR_iMsgCount; /* 管線消息隊列緩存個數 */ INT DCATTR_iPipeline; /* 處理管線線程數量 */ BOOL DCATTR_bParallel; /* 是否支持並行讀寫 */ ULONG DCATTR_ulReserved[8]; /* 保留 */ } LW_DISKCACHE_ATTR; typedef LW_DISKCACHE_ATTR *PLW_DISKCACHE_ATTR;
當設備支持併發讀寫時操做時,DCATTR_bParallel等於LW_TURE,不然爲LW_FALSE。DCATTR_iPipeline大於等於0且 小於 LW_CFG_DISKCACHE_MAX_PIPELINE。 DCATTR_iPipeline 等於0 表示不使用管線併發技術。DCATTR_iMsgCount 最小爲 DCATTR_iPipeline,能夠爲 DCATTR_iPipeline 2 ~ 8 倍。關於磁盤高速傳輸中使用的併發寫管線將在後續章節中介紹,本文不作過多說明。隊列
每一個磁盤CACHE塊設備由一個控制塊管理,該控制塊包含了各類控制信息,具體結構如程序清單 2-3所示。ip
程序清單 2-3 CACHE控制塊結構體
typedef struct { LW_BLK_DEV DISKC_blkdCache; /* DISK CACHE 的 BLK IO 控制塊 */ PLW_BLK_DEV DISKC_pblkdDisk; /* 被緩衝 BLK IO 控制塊地址 */ LW_LIST_LINE DISKC_lineManage; /* 背景線程管理鏈表 */ LW_OBJECT_HANDLE DISKC_hDiskCacheLock; /* DISK CACHE 操做鎖 */ INT DISKC_iCacheOpt; /* CACHE 工做選項 */ ULONG DISKC_ulEndStector; /* 最後一個扇區的編號 */ ULONG DISKC_ulBytesPerSector; /* 每一扇區字節數量 */ ULONG DISKC_ulValidCounter; /* 有效的扇區數量 */ ULONG DISKC_ulDirtyCounter; /* 須要回寫的扇區數量 */ INT DISKC_iMaxRBurstSector; /* 最大猝發讀寫扇區數量 */ INT DISKC_iMaxWBurstSector; LW_DISKCACHE_WP DISKC_wpWrite; /* 併發寫管線 */ PLW_LIST_RING DISKC_pringLruHeader; /* LRU 表頭 */ PLW_LIST_LINE *DISKC_pplineHash; /* HASH 表池 */ INT DISKC_iHashSize; /* HASH 表大小 */ ULONG DISKC_ulNCacheNode; /* CACHE 緩衝的節點數 */ caddr_t DISKC_pcCacheNodeMem; /* CACHE 節點鏈表首地址 */ caddr_t DISKC_pcCacheMem; /* CACHE 緩衝區 */ PLW_DISKCACHE_NODE DISKC_disknLuck; /* 幸運扇區節點 */ VOIDFUNCPTR DISKC_pfuncFsCallback; /* 文件系統回調函數 */ PVOID DISKC_pvFsArg; /* 文件系統回調參數 */ } LW_DISKCACHE_CB; typedef LW_DISKCACHE_CB *PLW_DISKCACHE_CB;
建立的過程主要包括:
1.建立回寫鎖和背景回寫線程
2.建立/proc中的文件節點
3.初始化磁盤
4.開闢控制塊內存
5.建立操做互斥信號量和併發寫隊列
6.建立HASH表池
7.開闢緩衝內存池
8.初始化BLK_DEV
9.將DISK CACHE塊加入背景線程
完成初始化後,CACHE塊設備以CACHE節點管理着每一個扇區,節點經過雙向鏈表構成一個LRU循環鏈表,最新使用的通常插入到表頭,最久未用或空節點通常在表尾。當節點被使用時,根據緩衝的扇區號將節點加入到對應的HASH錶鏈表中,方便下次查找時快速命中,詳細內容如程序清單 2-4所示。
程序清單 2-4 CACHE節點結構體
typedef struct { LW_LIST_RING DISKN_ringLru; /* LRU 表節點 */ LW_LIST_LINE DISKN_lineHash; /* HASH 表節點 */ ULONG DISKN_ulSectorNo; /* 緩衝的扇區號 */ INT DISKN_iStatus; /* 節點狀態 */ caddr_t DISKN_pcData; /* 扇區數據緩衝 */ UINT64 DISKN_u64FsKey; /* 文件系統自定義數據 */ } LW_DISKCACHE_NODE; typedef LW_DISKCACHE_NODE *PLW_DISKCACHE_NODE;
磁盤CACHE塊設備刪除接口爲API_DiskCacheDelete函數,刪除時須要等待全部寫操做完成後,刪除寫管線、退出背景線程、刪除信號量、釋放內存。
磁盤CACHE塊設備的回寫有多種接口,包括將指定扇區範圍回寫,將指定關鍵區回寫或將指定扇區數量回寫。此處以將磁盤CACHE的指定扇區數量回寫爲例,回寫時即查找LRU表中最後的若干數量的節點,若爲髒節點則插入到一個按照緩衝扇區號升序排列的鏈表中,同時將其從LRU表中刪除,若爲無效節點,則直接從有效的HASH表中刪除。
將有序鏈表中的CACHE節點所有回寫磁盤時,會先檢查是否爲連續扇區,若爲連續扇區則一次寫請求可寫多個扇區,不然一次回寫一個扇區。若磁盤緩衝器不支持多管線,則直接調用磁盤物理設備的寫接口,而多管線線程下,只需發送一個消息到寫管線線程,在寫管線線程中進行具體的寫操做。完成一個節點的回寫後,須要將節點從臨時回寫鏈表中刪除,並加入到磁盤CACHE的LRU鏈表結尾。
磁盤CACHE塊設備同步接口API_DiskCacheSync經過調用ioctl的FIOFLUSH實現將全部的緩衝所有回寫 ,操做流程與前述類似。
當文件系統須要進行讀寫操做時,最終會調用到磁盤對應的CACHE塊設備讀寫操做。此時,須要先獲取一個通過指定處理的CACHE節點。首先根據扇區號從有效的HASH表中查找,若找到則直接命中,不然開闢新的節點。建立一個CACHE塊時,若全部CACHE所有爲髒,或是沒法在LRU表中找到合適的控制塊,則須要作FLUSH操做,回寫一些扇區的數據,以後從新查找。查找時從LRU表的結尾向前查找,過程當中若發現無效扇區,須要從有效表中刪除。查找完成後,將找到的節點置爲有效,並加入到相關的HASH表中。若爲讀操做,根據是否爲直接命中,選擇是否須要從磁盤中讀取數據到CACHE塊中,若爲寫數據,則將CACHE塊設置髒位標記。最後,將該節點設置爲幸運節點,並從LRU表中從新設置到表頭。
在獲取到CACHE節點後,根據不一樣的操做,向CACHE中寫入數據,或從中讀取數據。
無