手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>网站运营>建站经验>列表

【转帖】Linux对I/O端口资源的管理 (1)

来源:互联网 作者:west263.com 时间:2008-04-16
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!

    {
  struct resource *conflict;
  
  write_lock(&resource_lock);
  conflict = __request_resource(root, new);
  write_unlock(&resource_lock);
  return conflict ? -EBUSY : 0;
    }
  
  
  
    对上述函数的NOTE如下:
  
    ①资源锁resource_lock对任何资源树进行读写保护,任何代码段在访问某一颗资源树之前都必须先持有该锁。其定义如下(kernel/Resource.c):
  
  
    static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
  
  
  
    ②能够看出,函数实际上是通过调用内部静态函数__request_resource()来完成实际的资源分配工作。假如该函数返回非空指针,则表示有资源冲突;否则,返回NULL就表示分配成功。
  
    ③最后,假如conflict指针为NULL,则request_resource()函数返回返回值0,表示成功;否则返回-EBUSY表示想要分配的资源已被占用。
  
    函数__request_resource()完成实际的资源分配工作。假如参数new所描述的资源中的一部分或全部已被其他节点所占用,则函数返回和new相冲突的resource结构的指针。否则就返回NULL。该函数的源代码如下
  
  
  (kernel/Resource.c):
  /* Return the conflict entry if you can't request it */
  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;
  for (;;) {
  tmp = *p;
  if (!tmp || tmp->start > end) {
  new->sibling = tmp;
  *p = new;
  new->parent = root;
  return NULL;
  }
  p = &tmp->sibling;
  if (tmp->end < start)
  continue;
  return tmp;
  }
  }
  
  
  
    对函数的NOTE:
  
    ①前三个if语句判断new所描述的资源范围是否被包含在root内,连同是否是一段有效的资源(因为end必须大于start)。否则就返回root指针,表示和根结点相冲突。
  
    ②接下来用一个for循环遍历根节点root的child链表,以便检查是否有资源冲突,并将new插入到child链表中的合适位置(child 链表是以I/O资源物理地址从低到高的顺序排列的)。为此,他用tmp指针指向当前正被扫描的resource结构,用指针p指向前一个resource 结构的sibling指针成员变量,p的初始值为指向root->sibling。For循环体的执行步骤如下:
  
    l 让tmp指向当前正被扫描的resource结构(tmp=*p)。
  
    l 判断tmp指针是否为空(tmp指针为空说明已遍历完整个child链表),或当前被扫描节点的起始位置start是否比new的结束位置end还要大。只要这两个条件之一成立的话,就说明没有资源冲突,于是就能够把new链入child链表中:①配置new的sibling指针指向当前正被扫描的节点tmp(new->sibling=tmp);②当前节点tmp的前一个兄弟节点的sibling指针被修改为指向new这个节点(*p= new);③将new的parent指针配置为指向root。然后函数就能够返回了(返回值NULL表示没有资源冲突)。
  
    l 假如上述两个条件都不成立,这说明当前被扫描节点的资源域有可能和new相冲突(实际上就是两个闭区间有交集),因此需要进一步判断。为此他首先修改指针 p,让他指向tmp->sibling,以便于继续扫描child链表。然后,判断tmp->end是否小于new->start,假如小于,则说明当前节点tmp和new没有资源冲突,因此执行continue语句,继续向下扫描child链表。否则,假如tmp->end大于或等于new->start,则说明tmp->[start,end]和new->[start,end]之间有交集。所以返回当前节点的指针tmp,表示发生资源冲突。
  
    3.2.2 资源的释放
  
    函数release_resource()用于实现I/O资源的释放。该函数只有一个参数——即指针old,他指向所要释放的资源。起源代码如下:
  
  
  int release_resource(struct resource *old)
  {
  int retval;
  
  write_lock(&resource_lock);
  retval = __release_resource(old);
  write_unlock(&resource_lock);
  return retval;
  }
  
  
  
    能够看出,他实际上通过调用__release_resource()这个内部静态函数来完成实际的资源释放工作。函数 __release_resource()的主要任务就是将资源区域old(假如已存在的话)从其父资源的child链表重摘除,他的源代码如下:
  
  
  static int __release_resource(struct resource *old)
  {
  struct resource *tmp, **p;
  
  p = &old->parent->child;
  for (;;) {
  tmp = *p;
  if (!tmp)
  break;
  if (tmp == old) {
  *p = tmp->sibling;
  old->parent = NULL;
  return 0;
  }
  p = &tmp->sibling;
  }
  return -EINVAL;
  }
  
  
  
    对上述函数代码的NOTE如下:
  

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!