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

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

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

    同函数__request_resource()相类似,该函数也是通过一个for循环来遍历父资源的child链表。为此,他让tmp指针指向当前被扫描的资源,而指针p则指向当前节点的前一个节点的sibling成员(p的初始值为指向父资源的child指针)。循环体的步骤如下:
  
    ①首先,让tmp指针指向当前被扫描的节点(tmp=*p)。
  
    ②假如tmp指针为空,说明已遍历完整个child链表,因此执行break语句推出for循环。由于在遍历过程中没有在child链表中找到参数old所指定的资源节点,因此最后返回错误值-EINVAL,表示参数old是个无效的值。
  
    ③接下来,判断当前被扫描节点是否就是参数old所指定的资源节点。假如是,那就将old从child链表中去除,也即让当前结点tmp的前一个兄弟节点的sibling指针指向tmp的下一个节点,然后将old->parent指针配置为NULL。最后返回0值表示执行成功。
  
    ④假如当前被扫描节点不是资源old,那就继续扫描child链表中的下一个元素。因此将指针p指向tmp->sibling成员。
  
    3.2.3 检查资源是否已被占用,
  
    函数check_resource()用于实现检查某一段I/O资源是否已被占用。其源代码如下:
  
  
  int check_resource(struct resource *root, unsigned long start, unsigned long len)
  {
  struct resource *conflict, tmp;
  
  tmp.start = start;
  tmp.end = start len - 1;
  write_lock(&resource_lock);
  conflict = __request_resource(root, &tmp);
  if (!conflict)
  __release_resource(&tmp);
  write_unlock(&resource_lock);
  return conflict ? -EBUSY : 0;
  }
  
  
  
    对该函数的NOTE如下:
  
    ①构造一个临时资源tmp,表示所要检查的资源[start,start end-1]。
  
    ②调用__request_resource()函数在根节点root申请tmp所表示的资源。假如tmp所描述的资源还被人使用,则该函数返回 NULL,否则返回非空指针。因此接下来在conflict为NULL的情况下,调用__release_resource()将刚刚申请的资源释放掉。
  
    ③最后根据conflict是否为NULL,返回-EBUSY或0值。
  
    3.2.4 寻找可用资源
  
    函数find_resource()用于在一颗资源树中寻找未被使用的、且满足给定条件的(也即资源长度大小为size,且在[min,max]区间内)的资源。其函数源代码如下:
  
  
  /*
  * Find empty slot in the resource tree given range and alignment.
  */
  static int find_resource(struct resource *root, struct resource *new,
  unsigned long size,
  unsigned long min, unsigned long max,
  unsigned long align,
  void (*alignf)(void *, struct resource *, unsigned long),
  void *alignf_data)
  {
  struct resource *this = root->child;
  
  new->start = root->start;
  for(;;) {
  if (this)
  new->end = this->start;
  else
  new->end = root->end;
  if (new->start < min)
  new->start = min;
  if (new->end > max)
  new->end = max;
  new->start = (new->start align - 1) & ~(align - 1);
  if (alignf)
  alignf(alignf_data, new, size);
  if (new->start < new->end && new->end - new->start 1 >= size)
  {
  new->end = new->start size - 1;
  return 0;
  }
  if (!this)
  break;
  new->start = this->end 1;
  this = this->sibling;
  }
  return -EBUSY;
  }
  
  
  
    对该函数的NOTE如下:
  
    同样,该函数也要遍历root的child链表,以寻找未被使用的资源空洞。为此,他让this指针表示当前正被扫描的子资源节点,其初始值等于 root->child,即指向child链表中的第一个节点,并让new->start的初始值等于root->start,然后用一个for循环开始扫描child链表,对于每一个被扫描的节点,循环体执行如下操作:
  
    ①首先,判断this指针是否为NULL。假如不为空,就让new->end等于this->start,也即让资源new表示当前资源节点this前面那一段未使用的资源区间。
  
    ②假如this指针为空,那就让new->end等于root->end。这有两层意思:第一种情况就是根结点的child指针为 NULL(即根节点没有任何子资源)。因此此时先暂时将new->end放到最大。第二种情况就是已遍历完整个child链表,所以此时就让 new表示最后一个子资源后面那一段未使用的资源区间。
  
    ③根据参数min和max修正new->[start,end]的值,以使资源new被包含在[min,max]区域内。
  
    ④接下来进行对齐操作。
  
    ⑤然后,判断经过上述这些步骤所形成的资源区域new是否是一段有效的资源(end必须大于或等于start),而且资源区域的长度满足size参数的需要(end-start+1>=size)。假如这两个条件均满足,则说明我们已找到了一段满足条件的资源空洞。因此在对new-> end的值进行修正后,然后就能够返回了(返回值0表示成功)。
  
    ⑥假如上述两条件不能同时满足,则说明还没有找到,因此要继续扫描链表。在继续扫描之前,我们还是要判断一下this指针是否为空。假如为空,说明已扫描完整个child链表,因此就能够推出for循环了。否则就将new->start的值修改为this->end 1,并让this指向下一个兄弟资源节点,从而继续扫描链表中的下一个子资源节点。

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