Linux高端内存映射(下)


非连续内存分配

非连续内存分配是指将物理地址不连续的页框映射到线性地址连续的线性地址空间,主要应用于大容量的内存分配。采用这种方式分配内存的主要优点是避免了外部碎片,而缺点是必须打乱内核页表,而且访问速度较连续分配的物理页框慢。

 

相关阅读:

Linux高端内存映射(上) 
Linux高端内存映射(中) 
Linux高端内存映射(中) 

非连续内存分配的线性地址空间是从VMALLOC_START到VMALLOC_END(具体可以参见<<Linux高端内存映射(上)>>),共128M,每当内核要用vmalloc类的函数进行非连续内存分配,就会申请一个vm_struct结构来描述对应的vmalloc区,两个vmalloc区之间的间隔至少为一个页框的大小,即PAGE_SIZE。下图是非连续内存分配区的示意图

                                               

所有的vm_struct都会链入vmlist链表来管理,从2.6的某个内核版本开始,为了提高效率,内核又为vmalloc区添加了vmap_area结构和vm_struct共同描述,并且引入了红黑树来组织这些结构,鉴于红黑树的复杂,为了简化讨论,把重心放在非连续内存分配的机制上,涉及到vmap_area的具体代码不做详细的分析。

数据结构描述

在分析具体的代码之前,我们先了解描述vmalloc区的这两个数据结构

  1. struct vm_struct {  
  2.     struct vm_struct    *next;       /*指向下一个vm区域*/  
  3.     void                *addr;       /*指向第一个内存单元(线性地址)*/  
  4.     unsigned long       size;        /*该块内存区的大小*/  
  5.     unsigned long       flags;       /*内存类型的标识字段*/  
  6.     struct page        **pages;        /*指向页描述符指针数组*/  
  7.     unsigned int        nr_pages;    /*内存区大小对应的页框数*/  
  8.     unsigned long       phys_addr;   /*用来映射硬件设备的IO共享内存,其他情况下为0*/  
  9.     void                *caller;     /*调用vmalloc类的函数的返回地址*/  
  10. };  

 

  1. struct vmap_area {  
  2.     unsigned long va_start;       /*malloc区的起始地址*/  
  3.     unsigned long va_end;         /*malloc区的结束地址*/  
  4.     unsigned long flags;          /*类型标识*/  
  5.     struct rb_node rb_node;    /* address sorted rbtree */  
  6.     struct list_head list;         /* address sorted list */  
  7.     struct list_head purge_list; /* "lazy purge" list */  
  8.     void *private;                /*指向配对的vm_struct*/  
  9.     struct rcu_head rcu_head;  
  10. };  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 下一页

相关内容

    暂无相关文章