1. 程式人生 > >SylixOS磁盤高速傳輸

SylixOS磁盤高速傳輸

程序 模型 結構體 多線程

  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. 參考資料

SylixOS磁盤高速傳輸