1. 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:排空信號,用于回寫完成后同步。

  2. 寫管線創建

    寫管線的創建通過調用__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. 創建管線緩存

    2. 創建管線刷新隊列

    3. 創建計數信號量

    4. 創建內存分區緩存管理

    5. 創建排空信號

    6. 創建非并發設備鎖

    7. 創建寫管線線程組

  3. 寫管線線程

    寫管線線程的函數原型如程序清單 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;

    ?

    當線程接收到消息后,根據消息中的信息調用具體的硬件接口進行寫操作。完成寫操作后,需要釋放消息中的內存塊以及計數信號量和同步信號,接著進入下一次循環等待接收消息。

  4. 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信號量實現同步功能。

  5. 參考資料