SylixOS 内存管理-通过地址反查页面控制块-vmmArea.c

在vmm文件夹中的vmmArea.c文件是实现页表控制块反查功能。通过给定的地址(虚拟或者物理)可以查找到对应页面控制块LW_VMM_PAGE。 系统是通过哈希红黑树来实现这个功能的。首先在zone包含了一个哈希表。通过哈希索引值找到对应的红黑树根。也zone页面管理类似,页面关系是通过哈希表插到对应的链表头。有几个比较重要的结构体。LW_VMM_AREA 是一个非常重要的结构,它包含了一个哈希表。这是一个红黑树树哈希表。

下图中index代表的就是哈希表的索引值,哈希表就是LW_VMM_AREA中的 

+------+----+-------+---------+-------+------+--------+----------+-------+
|      |    |       |         |       |      |        |          |       |
| index|    |       |         |       |      |        |          |       |
+-+---------+-------+---------+-------+------+--------+----------+-------+
  |
  |
  |
  |
  |                                       +-----------------+
  |                                       | PLW_VMM_PAGE    |
  |                                       |                 |
  |      +---------------+                +-----------------+
  |      |               |                |                 |
  |      |PLW_VMM_PAGE   |     +--------->+LW_TREE_RB_NODE  |
  |      +---------------+     |          +-----------------+
  |      |               +-----+          |                 |
  +----->+LW_TREE_RB_NODE+---+            |                 |
         +---------------+   |            |                 |
         |               |   |            |                 |
         |               |   |            +-----------------+
         +---------------+   |
                             |
                             |
                             |            +-----------------+
                             |            | PLW_VMM_PAGE    |
                             |            |                 |
                             |            +-----------------+
                             |            |                 |
                             |            | LW_TREE_RB_NODE |
                             +----------->+                 |
                                          +-----------------+
                                          |                 |
                                          |                 |
                                          |                 |
                                          +-----------------+

__areaVirtualSpaceInit

此函数是初始化虚拟地址的反查表。主要是创建哈希表。

/*********************************************************************************************************
** 函数名称: __areaVirtualSpaceInit
** 功能描述: 初始化虚拟地址空间管理块
** 输 入  : pvirdes       虚拟空间描述
** 输 出  : ERROR CODE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
ULONG  __areaVirtualSpaceInit (LW_MMU_VIRTUAL_DESC   pvirdes[])
{
    REGISTER PLW_MMU_CONTEXT  pmmuctx = __vmmGetCurCtx();
             INT              i;
             addr_t           ulAddr  = __ARCH_ULONG_MAX;
             addr_t           ulEnd   = 0;
    
    for (i = 0; i < LW_CFG_VMM_VIR_NUM; i++) {
        if (pvirdes[i].VIRD_stSize == 0) {
            break;
        }
        if (ulAddr > pvirdes[i].VIRD_ulVirAddr) {
            ulAddr = pvirdes[i].VIRD_ulVirAddr;
        }
        if (ulEnd < (pvirdes[i].VIRD_ulVirAddr + pvirdes[i].VIRD_stSize)) {
            ulEnd = (pvirdes[i].VIRD_ulVirAddr + pvirdes[i].VIRD_stSize);
        }
    }
    
    if (ulAddr == __ARCH_ULONG_MAX) {
        _ErrorHandle(ENOSPC);
        return  (ENOSPC);
    }
    
    return  (__areaSpaceInit(&pmmuctx->MMUCTX_vmareaVirSpace, ulAddr, (size_t)(ulEnd - ulAddr)));
}

虚拟地址描述符指定了虚拟地址的起始地址和大小。查找其中地址最小值和最大值。相减就是size。从mmu上下文中获得LW_VMM_AREA,虚拟地址是一个LW_VMM_AREA。物理地址是多个。

然后调用__areaSpaceInit函数。

 此函数根据地址长度选择合适大小的哈希表。

选择合适哈希表大小后,给关键数据赋值,然后分配哈希表空间。

 __areaPhysicalSpaceInit

此函数是物理地址反查表初始化。

ULONG  __areaPhysicalSpaceInit (LW_MMU_PHYSICAL_DESC  pphydesc[])
{
    REGISTER ULONG  ulError = ERROR_NONE;
    static   ULONG  ulZone  = 0;                                        /*  可多次追尾添加内存          */
             INT    i;
             
    for (i = 0; ; i++) {
        if (pphydesc[i].PHYD_stSize == 0) {
            break;
        }
        
        switch (pphydesc[i].PHYD_uiType) {
        
        case LW_PHYSICAL_MEM_DMA:
        case LW_PHYSICAL_MEM_APP:
            if (ulZone < LW_CFG_VMM_ZONE_NUM) {
                ulError = __areaSpaceInit(&_G_vmareaZoneSpace[ulZone], 
                                          pphydesc[i].PHYD_ulPhyAddr, 
                                          pphydesc[i].PHYD_stSize);
                if (ulError) {
                    _ErrorHandle(ulError);
                    return  (ulError);
                }
                ulZone++;
            }
            break;
            
        default:
            break;
        }
    }

    return  (ERROR_NONE);
}

和虚拟地址初始化一样都会调用__areaSpaceInit函数。不过物理地址对物理地址描述符中的DMA和APP属性才创建反差表。并且指定了多个LW_VMM_AREA。

 __areaInsertPage

此函数是往红黑树中插入一个页面管理块。

/*********************************************************************************************************
** 函数名称: __areaInsertPage
** 功能描述: 向地址空间中注册一个页面控制块
** 输 入  : pvmarea       地址空间管理块
**           ulAddr        起始地址
**           pvmpage       页面控制块
** 输 出  : NONE
** 全局变量: 
** 调用模块: 
*********************************************************************************************************/
static VOID  __areaInsertPage (PLW_VMM_AREA  pvmarea, addr_t  ulAddr, PLW_VMM_PAGE  pvmpage)
{
             ULONG              ulHashIndex;
    REGISTER PLW_TREE_RB_ROOT   ptrbr;
    REGISTER PLW_TREE_RB_NODE  *pptrbnRoot;
    REGISTER PLW_TREE_RB_NODE   ptrbnParent = LW_NULL;
             PLW_VMM_PAGE       pvmpageTemp;
    
    ulHashIndex = __VMM_AREA_HASH_INDEX(pvmarea, ulAddr);
    ptrbr       = &pvmarea->AREA_ptrbrHash[ulHashIndex];                /*  确定 hash 表位置            */
    
    pptrbnRoot = &ptrbr->TRBR_ptrbnNode;
    
    while (*pptrbnRoot) {
        ptrbnParent = *pptrbnRoot;
        
        pvmpageTemp = _TREE_ENTRY(ptrbnParent, LW_VMM_PAGE, PAGE_trbnNode);
        
        if (ulAddr < pvmpageTemp->PAGE_ulPageAddr) {
            pptrbnRoot = _tree_rb_get_left_addr(*pptrbnRoot);
        } else if (ulAddr > pvmpageTemp->PAGE_ulPageAddr) {
            pptrbnRoot = _tree_rb_get_right_addr(*pptrbnRoot);
        } else {
            return;                                                     /*  不可能运行到这里            */
        }
    }
    
    _tree_rb_link_node(&pvmpage->PAGE_trbnNode, 
                       ptrbnParent, 
                       pptrbnRoot);                                     /*  插入到树中                  */
                       
    _Tree_Rb_Insert_Color(&pvmpage->PAGE_trbnNode, 
                          &pvmarea->AREA_ptrbrHash[ulHashIndex]);       /*  维持平衡                    */
}

在插入前首先要计算哈希表的索引值index。SylixOS 使用的计算公式如下:

 算出索引值index 后就可以获得对应的红黑树树根。对于根节点第一次插入时根结点TRBR_ptrbnNode指针为空。所以不进入while循环,直接调用_tree_rb_link_node,_Tree_Rb_Insert_Color两个函数,将vmpage中红黑树节点地址赋值给TRBR_ptrbnNode。当不是首次插入时按照正常差分查找,然后加入到树中,最后平衡树。

__areaSearchPage

此函数是在哈希红黑树中查找对应的addr,先找到红黑树node对应的结构体母体vmpage,然后地址和vmpage中的地址比对大小,不断查找,相等时就返回这个vmpage。

__areaUnlinkPage

此函数是从红黑树中删除一个vmpage节点,首先还是先获得哈希表中索引值,获得红黑树的根节点,然后调用红黑树库函数删除当前节点。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值