SylixOS磁盘高速传输

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huikai309/article/details/73250622
  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. 参考资料

猜你喜欢

转载自blog.csdn.net/huikai309/article/details/73250622