Linux下虚拟空间的管理
如果说物理空间是从“供”的角度管理的,那么虚拟空间的管理就是从“需”的角度管理的。就是我们需要虚存空间的哪些部分。
一个进程所需要使用的虚拟空间中各个部位又未必是连续的,通常形成若干离散的虚存"区间"。在Linux内核中,对虚拟区间的就是vm_area_struct数据结构。
struct vm_area_struct
{
struct mm_struct *vm_mm; /* The address space we belong to. */
unsigned long vm_start; /* Our start address within vm_mm. */
unsigned long vm_end; /* The first byte after our end address
within vm_mm. */
....
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct *vm_next;
....
/* describe the permissable operation */
unsigned long vm_flags;
/* operations on this area */
struct vm_operations_struct * vm_ops;
struct file * vm_file; /* File we map to (can be NULL). */
} ;
结构中的vm_start 和vm_end决定一个虚存空间。vm_start是包括在区间内的,而vm_end则不包括在区间内。区间的划分并不仅仅取决于地址的连续性,也取决于区间的其他属性,主要是对虚拟页面的访问权限。包含在同一个区间里的所有页面应该有相同的访问权限(或保护权限)和一些其它权限。这就是结构中的成分vm_page_porthe vm_flags的用途。
属于同一个进程的所有区间都是按虚拟内存的高低次序链接在一起。(vm_next)
在vm_area_struct中还有一个指针vm_mm,该指针指向一个mm_struct数据结构;这是比vm_area_struct更高层次的数据结构。
struct mm_struct
{
struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb;
struct vm_area_struct *mmap_cache; /* last find_vma result */
...
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack;
...
};
mm_struct数据结构是整个用户空间的抽象。
第一个mmap用来建立一个虚拟区间结构的单链线性队列。
第二个mm_rb建立虚拟区间的红黑树。(红黑树的查找效率远大于单链表);
第三个mm_cache,用于指向最近一次用过的虚存区间结构。(程序运行的局部性原理,最近一次用到的区间很可能就是下一次要用的区间)。
当查找虚拟空间时,
find_vma(),先查找mm_cache,没有找到再从红黑树(或链表)中查找,找到后将mm_cache指针指向找到的vm_area_struct 。
如果find_vma()返回值为0,表示该地址所属区间还未建立。调用insert_vm_struct()将其插入到mm_struct中红黑树或链表中去。