科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Linux操作系统对I/O端口资源的管理 (3)

Linux操作系统对I/O端口资源的管理 (3)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

节点root、r1、r2和r3实际上都是一个resource结构类型。子资源r1、r2和r3通过sibling指针链接成一条单向非循环链表,其表头由root节点中的child指针定义,因此也称为父资源的子资源链表。

作者:linuxaid.com 来源:linuxaid.com 2007年10月21日

关键字: 管理 资源 I/O Linux

  • 评论
  • 分享微博
  • 分享邮件
 

I/O资源的申请

假设某类资源有如下这样一颗资源树:

节点root、r1、r2和r3实际上都是一个resource结构类型。子资源r1、r2和r3通过sibling指针链接成一条单向非循环链表,其表头由root节点中的child指针定义,因此也称为父资源的子资源链表。r1、r2和r3的parent指针均指向他们的父资源节点,在这里也就是图中的root节点。

假设想在root节点中分配一段I/O资源(由图中的阴影区域表示)。函数request_resource()实现这一功能。它有两个参数:①root指针,表示要在哪个资源根节点中进行分配;②new指针,指向描述所要分配的资源(即图中的阴影区域)的resource结构。该函数的源代码如下(kernel/resource.c):

  
  
  int request_resource(struct resource *root, struct resource *new)
    {
  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循环体的执行步骤如下:

让tmp指向当前正被扫描的resource结构(tmp=*p)。

判断tmp指针是否为空(tmp指针为空说明已经遍历完整个child链表),或者当前被扫描节点的起始位置start是否比new的结束位置end还要大。只要这两个条件之一成立的话,就说明没有资源冲突,于是就可以把new链入child链表中:①设置new的sibling指针指向当前正被扫描的节点tmp(new->sibling=tmp);②当前节点tmp的前一个兄弟节点的sibling指针被修改为指向new这个节点(*p=new);③将new的parent指针设置为指向root。然后函数就可以返回了(返回值NULL表示没有资源冲突)。

如果上述两个条件都不成立,这说明当前被扫描节点的资源域有可能与new相冲突(实际上就是两个闭区间有交集),因此需要进一步判断。为此它首先修改指针p,让它指向tmp->sibling,以便于继 续扫描child链表。然后,判断tmp->;end是否小于new->;start,如果小于,则说明当前节点tmp和new没有资源冲突,因此执行continue语句,继续向下扫描child链表。否则,如果tmp->;end大于或等于new->;start,则说明tmp->;[start,end]和new->;[start,end]之间有交集。所以返回当前节点的指针tmp,表示发生资源冲突。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章