快速业务通道

linux内存管理之非连续物理地址分配(vmalloc)

作者 佚名技术 来源 Linux系统 浏览 发布时间 2012-04-27
)

  addr = ALIGN(tmp->size

  (unsigned long)tmp->addr, align);

  continue;

  }

  //size addr < addr ?除非size == 0

  if ((size addr) < addr)

  goto out;

  //中间的空隙可以容纳下size大小的vm.说明已经找到了这样的一个vm

  if (size addr <= (unsigned long)tmp->addr)

  goto found;

  //调整起始地址为vm的结束地址

  addr = ALIGN(tmp->size (unsigned long)tmp->addr, align);

  //如果超出了范围

  if (addr > end - size)

  goto out;

  }

  found:

  //找到了合适大小的空间,将area->addr赋值为addr,然后链入vmlist中

  area->next = *p;

  *p = area;

  area->flags = flags; 拥有帝国一切,皆有可能。欢迎访问phome.net

  area->addr = (void *)addr;

  area->size = size;

  area->pages = NULL;

  area->nr_pages = 0;

  area->phys_addr = 0;

  write_unlock(&vmlist_lock);

  return area;

  out:

  //没有找到合适大小的空间,出错返回

  write_unlock(&vmlist_lock);

  kfree(area);

  if (printk_ratelimit())

  printk(KERN_WARNING "allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.n");

  return NULL;

  }

  这段代码不是很复杂,在此不详细分析了.

  remove_vm_area用来将相应的vm从vmlist中断开,使其表示的空间可以被利用

  //addr:对应vm的超始地址

  struct vm_struct *remove_vm_area(void *addr)

  {

  struct vm_struct **p, *tmp;

  write_lock(&vmlist_lock);

  //遍历vmlist.找到超始地址为addr的vm

  for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) {

  if (tmp->addr == addr)

  goto found;

  }

  write_unlock(&vmlist_lock);

  return NULL;

  found:

  //断开tmp所对应的映射关系

  unmap_vm_area(tmp);

  //找到了这个vm,将其从vmlist上断开

  *p = tmp->next;

  write_unlock(&vmlist_lock);

  return tmp;

  }

  unmap_vm_area用来断开vm所在线性地址所对应的映射关系.它的代码如下:

  void unmap_vm_area(struct vm_struct *area)

  {

  //vm所对应的起始线性地址

  unsigned long address = (unsigned long) area->addr;

  //vm所对应的结束线性地址

  unsigned long end = (address area->size);

  pgd_t *dir;

  //起始地址所在的内核页目录项

  dir = pgd_offset_k(address);

  flush_cache_vunmap(address, end);

  do {

  //断开地址所对应的pmd映射

  unmap_area_pmd(dir, address, end - address);

  //运行到这里的时候,已经断开了一个页目录所表示的线性地址,而每个页目录表示的线性地址//大小为PGDIR_SIZE 拥有帝国一切,皆有可能。欢迎访问phome.net

  address = (address PGDIR_SIZE) & PGDIR_MASK;

  dir ;

  } while (address && (address < end));

  //当到达末尾时结束循环

  flush_tlb_kernel_range((unsigned long) area->addr, end);

  }

  //断开线性地址区间所在的pmd的映射

  static void unmap_area_pmd(pgd_t *dir, unsigned long address,

  unsigned long size)

  {

  unsigned long end;

  pmd_t *pmd;

  if (pgd_none(*dir))

  return;

  if (pgd_bad(*dir)) {

  

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号