linux下request_mem_region的粗略理解

linuxrequest_mem_region的粗略理解

文章来源:http://gliethttp.cublog.cn

  Linux把基于I/O映射方式的I/O端口和基于内存映射方式的I/O端口资源统称为“I/O区域I/O Region)。I/O Region仍然是一种I/O资源,因此它仍然可以用resource结构类型来描述。

  Linux是以一种倒置的树形结构来管理每一类I/O资源(如:I/O端口、外设内存、DMAIRQ)的。每一类I/O资源都对应有一颗倒置的资源树,树中的每一个节点都是一个resource结构,而树的根结点root则描述了该类资源的整个资源空间。


1 . 结构体
  1 . 1 > struct resource iomem_resource = { "PCI mem" , 0x00000000 , 0xffffffff , IORESOURCE_MEM };
  1 . 2 > struct resource {
                 const char * name ;
                 unsigned long start , end ;
                 unsigned long flags ;
                 struct resource * parent , * sibling , * child ;
              };
2 . 调用函数
  request_mem_region ( S1D_PHYSICAL_REG_ADDR , S1D_PHYSICAL_REG_SIZE , "EpsonFB_RG" )
# define request_mem_region ( start , n , name ) __request_region (& iomem_resource , ( start ), ( n ), ( name ))
__request_region 检查是否可以安全占用起始物理地址S1D_PHYSICAL_REG_ADDR之后的连续S1D_PHYSICAL_REG_SIZE字节大小空间

struct resource * __request_region ( struct resource * parent , unsigned long start , unsigned long n , const char * name )
{
     struct resource * res = kmalloc ( sizeof (* res ), GFP_KERNEL );

     if ( res ) {
         memset ( res , 0 , sizeof (* res ));
        res -> name = name ;
        res -> start = start ;
        res -> end = start + n - 1 ;
        res -> flags = IORESOURCE_BUSY ;

        write_lock (& resource_lock );

         for (;;) {
             struct resource * conflict ;

            conflict = __request_resource ( parent , res );      //sibling parent 下的所有单元,检测申请部分是否存在交叠冲突
             if (! conflict )                                 //conflict=0; 申请成功,正常安置了[start,end]到相应位置
                 break ;
             if ( conflict != parent ) {
                parent = conflict ;
                 if (!( conflict -> flags & IORESOURCE_BUSY ))
                     continue ;
             }
             kfree ( res );                                     // 检测到了资源交叠冲突,kfree归还kmalloc申请的内存
            res = NULL ;
             break ;
         }
        write_unlock (& resource_lock );
     }
     return res ;
}

static struct resource * __request_resource ( struct resource * root , struct resource * new )
{
     unsigned long start = new -> start ;
     unsigned long end = new -> end ;
     struct resource * tmp , ** p ;

     if ( end < start )
         return root ;
     if ( start < root -> start )
         return root ;
     if ( end > root -> end )
         return root ;
    p = & root -> child ;                                       //root 下的第一个链表元素*p.[child链表是以I/O资源物理地址从低到高的顺序排列的]
     for (;;) {
        tmp = * p ;
         if (! tmp || tmp -> start > end ) {
             new -> sibling = tmp ;
             * p = new ;
// 可以从root->child=null开始我们的分析考虑,此时tmp=null,那么第一个申请将以!tmp条件满足而进入
// 这时root->child的值为new指针,new->sibling = tmp = null;当第二次申请发生时:如果tmp->start > end成立,
// 那么,root->child的值为new指针,new->sibling = tmp;这样就链接上了,空间分布图如:
//child=[start,end]-->[tmp->start,tmp->end](1); 如果条件tmp->start > end不成立,那么只能是!tmp条件进入
// 那么,root->child的值不变,tmp->sibling = new;new->sibling = tmp = null这样就链接上了,空间分布图如:
//child=[child->start,child->end]-->[start,end](2);
// 当第三次申请发生时:如果start(2)中的[child->end,end]之间,那么tmp->end < start将成立,继而continue,
// 此时tmp = (2)中的[start,end],因为tmp->start < end,所以继续执行p = &tmp->slibing = null,
// 因为tmp->end > start,所以资源冲突,返回(2)中的[start,end]
// 综上的两个边界值情况和一个中间值情况的分析,可以知道代码实现了一个从地地址到高地址的顺序链表
// 模型图:childe=[a,b]-->[c,d]-->[e,f],此时有一个[x,y]需要插入进去,tmp作为sibling指针游动
//tmp 指向child=[a,b],
//tmp 指向[a,b],tmp->start>y,插入后的链接图为:child=[x,y]-->[a,b]-->[c,d]-->[e,f]-->null;tmp->end>=x,冲突返回tmp
//tmp 指向[c,d],tmp->start>y,插入后的链接图为:child=[a,b]-->[x,y]-->[c,d]-->[e,f]-->null;tmp->end>=x,冲突返回tmp
//tmp 指向[e,f],tmp->start>y,插入后的链接图为:child=[a,b]-->[c,d]-->[x,y]-->[e,f]-->null;tmp->end>=x,冲突返回tmp
//tmp 指向null                  ,插入后的链接图为:child=[a,b]-->[c,d]-->[e,f]-->[x,y]-->null;
// 顺利的达到了检测冲突,顺序链接的目的
             new -> parent = root ;     
             return NULL ;
         }
        p = & tmp -> sibling ;
         if ( tmp -> end < start )
             continue ;
         return tmp ;
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值