SylixOS磁盤高速傳輸
SylixOS管線模型分析
前文主要介紹了SylixOS中的塊設備CACHE管理,本章主要介紹磁盤高速傳輸。在CAHCE回寫中SyilxOS采取了兩種方式,即直接回寫和多管線並發回寫。並發寫管線通過多線程並發處理CACHE提交的寫請求,實現磁盤高速傳輸。
SylixOS中通過LW_DISKCACHE_WP結構體管理並發寫管線,該結構體的具體內容如程序清單 1-1所示。
程序清單 1-1
typedef struct { BOOL DISKCWP_bExit; /* 是否需要退出 */ BOOL DISKCWP_bCacheCoherence; /* CACHE 一致性標誌 */ BOOL DISKCWP_bParallel; /* 並行化讀寫支持 */ INT DISKCWP_iPipeline; /* 寫管線線程數 */ INT DISKCWP_iMsgCount; /* 寫消息緩沖個數 */ PVOID DISKCWP_pvRBurstBuffer; /* 管線緩存 */ PVOID DISKCWP_pvWBurstBuffer; /* 管線緩存 */ LW_OBJECT_HANDLE DISKCWP_hMsgQueue; /* 管線刷新隊列 */ LW_OBJECT_HANDLE DISKCWP_hCounter; /* 計數信號量 */ LW_OBJECT_HANDLE DISKCWP_hPart; /* 管線緩存管理 */ LW_OBJECT_HANDLE DISKCWP_hSync; /* 排空信號 */ LW_OBJECT_HANDLE DISKCWP_hDev; /* 非並發設備鎖 */ LW_OBJECT_HANDLE DISKCWP_hWThread[LW_CFG_DISKCACHE_MAX_PIPELINE]; /* 管線寫任務表 */ } LW_DISKCACHE_WP; typedef LW_DISKCACHE_WP *PLW_DISKCACHE_WP;
DISKCWP_bExit:為LW_TRUE時,寫管線線程將會退出;
DISKCWP_bCacheCoherence:為LW_TRUE時,管線緩存將使用非緩沖的內存;
DISKCWP_bParallel:並行化讀寫支持,如果不支持則需要在操作設備前調用設備鎖,防止並發操作;
DISKCWP_iPipeline:寫管線線程數,為0時表示不是用並發寫管線;
DISKCWP_iMsgCount:寫消息緩沖個數,最小為DCATTR_iPipeline, 可以為 DCATTR_iPipeline 的2 ~ 8 倍;
DISKCWP_hMsgQueue:管線刷新隊列,上層通過發送一個消息,發起一個寫請求;
DISKCWP_hCounter:計數信號量,用於計數當前緩沖塊,發起寫請求時申請,完成回寫時釋放;
DISKCWP_hPart:通過定長內存管理管線緩存;
DISKCWP_hDev:非並發設備鎖;
DISKCWP_hWThread:管線寫任務表;
DISKCWP_hSync:排空信號,用於回寫完成後同步。
寫管線創建
寫管線的創建通過調用__diskCacheWpCreate函數來完成,其函數原型如程序清單 1-2所示。
程序清單 1-2
INT __diskCacheWpCreate(PLW_DISKCACHE_CB pdiskc, PLW_DISKCACHE_WP pwp, BOOL bCacheCoherence, BOOL bParallel, INT iPipeline, INT iMsgCount, INT iMaxRBurstSector, INT iMaxWBurstSector, ULONG ulBytesPerSector);
函數__diskCacheWpCreate原型分析:
pdiskc: 緩沖控制塊
pwp: 並發寫管線控制塊
bCacheCoherence: CACHE 一致性需求
bParallel: 並發讀寫支持
iPipeline: 寫管線線程數
iMsgCount: 管線總消息個數
iMaxRBurstSector: 讀猝發長度
iMaxWBurstSector: 寫猝發長度
ulBytesPerSector: 每扇區大小
函數__diskCacheWpCreate根據入參創建對應的寫管線,並填充相關信息到並發寫管線控制控制結構體,其創建流程如下所示。
創建管線緩存
創建管線刷新隊列
創建計數信號量
創建內存分區緩存管理
創建排空信號
創建非並發設備鎖
創建寫管線線程組
寫管線線程
寫管線線程的函數原型如程序清單 1-3所示。
程序清單 1-3
static PVOID __diskCacheWpThread (PVOID pvArg)
參數pvArg為PLW_DISKCACHE_CB類型的磁盤緩沖控制塊。管線線程運行後,循環等待接收管線刷新消息。其中消息類型如程序清單 1-4所示。
程序清單 1-4
typedef struct { ULONG DISKCWPM_ulStartSector; /* 起始扇區 */ ULONG DISKCWPM_ulNSector; /* 扇區數量 */ PVOID DISKCWPM_pvBuffer; /* 扇區緩沖 */ } LW_DISKCACHE_WPMSG; typedef LW_DISKCACHE_WPMSG *PLW_DISKCACHE_WPMSG;
當線程接收到消息後,根據消息中的信息調用具體的硬件接口進行寫操作。完成寫操作後,需要釋放消息中的內存塊以及計數信號量和同步信號,接著進入下一次循環等待接收消息。
SyilxOS管線使用
當支持並發寫管線時,可以通過調用__diskCacheWpGetBuffer函數在已初始化後的內存分區中申請一個內存塊,該函數的具體實現如程序清單 2-1所示。
程序清單 2-1
PVOID __diskCacheWpGetBuffer (PLW_DISKCACHE_WP pwp, BOOL bRead) { PVOID pvRet; if (bRead) { return (pwp->DISKCWP_pvRBurstBuffer); } if (pwp->DISKCWP_iPipeline == 0) { return (pwp->DISKCWP_pvWBurstBuffer); } if (API_SemaphoreCPend(pwp->DISKCWP_hCounter, LW_OPTION_WAIT_INFINITE)) { _BugHandle(LW_TRUE, LW_TRUE, "diskcache pipeline error!\r\n"); } pvRet = API_PartitionGet(pwp->DISKCWP_hPart); _BugHandle((pvRet == LW_NULL), LW_TRUE, "diskcache pipeline error!\r\n"); return (pvRet); }
在申請內存塊前,需要先請求計數信號量,計數信號量與內存塊數量相等。當內存分區中已沒有剩余的內存塊時,線程無法獲得計數信號量進入休眠。當管線線程完成寫操作後會釋放接收到的內存塊,並釋放計數信號量,此時休眠線程成功申請信號量進入就緒態,並順利獲得內存塊。
接著需要將CACHE中的緩沖數據拷貝到內存塊中,並提交一個寫請求。管線線程接收到消息後進行具體的寫操作和資源釋放。寫請求函數如程序清單 2-2所示。
程序清單 2-2
INT __diskCacheWpWrite (PLW_DISKCACHE_CB pdiskc, PLW_BLK_DEV pblkdDisk, PVOID pvBuffer, ULONG ulStartSector, ULONG ulNSector) { LW_DISKCACHE_WPMSG diskcwpm; PLW_DISKCACHE_WP pwp = &pdiskc->DISKC_wpWrite; if (pwp->DISKCWP_iPipeline == 0) { return (pdiskc->DISKC_pblkdDisk->BLKD_pfuncBlkWrt(pblkdDisk, pvBuffer, ulStartSector, ulNSector)); } diskcwpm.DISKCWPM_ulStartSector = ulStartSector; diskcwpm.DISKCWPM_ulNSector = ulNSector; diskcwpm.DISKCWPM_pvBuffer = pvBuffer; API_MsgQueueSend2(pwp->DISKCWP_hMsgQueue, &diskcwpm, sizeof(LW_DISKCACHE_WPMSG), LW_OPTION_WAIT_INFINITE); return (ERROR_NONE); }
發起寫請求後可通過調用__diskCacheWpSync函數進行寫同步,該函數通過寫管線控制塊中的DISKCWP_hSync信號量實現同步功能。
參考資料
無
SylixOS磁盤高速傳輸