进程地址空间

内核除了管理本身的内存之外,还必须管理用户空间中进程的内存,即进程地址空间。

一、内存描述符

内核使用内存描述符结构体表示进程的地址空间,该结构包含了和进程地址空间有关的全部信息,内存描述符由mm_struct结构体表示。

struct mm_struct {
    struct vm_area_struct *mmap;
    struct rb_root mm_rb;
    //...
};

mmap和mm_rb这两个不同数据结构体描述的对象是相同的:该地址空间中的全部内存区域,前者以链表形式存放而后者以红黑树的形式存放。 mmap结构体作为链表,利于简单、高效地遍历所有元素,而mm_rb结构体作为红黑树,更适合搜索指定元素。

在进程的进程描述符task_struct结构体中,mm域存放着该进程使用的内存描述符。是否共享地址空间几乎是进程和Linux中所谓的线程本质上的唯一区别。除此之外,Linux内核并不区别对待它们,线程对内核来说仅仅是一个共享特定资源的进程而已。

内核线程没有进程地址空间,也没有相关的内存描述符,所以内核线程对应的进程描述符中mm域为空。当一个进程被调度时,该进程的mm域指向的地址空间被装载到内存,进程描述符中的active_mm域会被更新,指向新的地址空间。内核线程没有地址空间,所以mm域为NULL,于是,当一个内核线程被调度时,内核发现它的mm域为NULL,就会保留前一个进程的地址空间,随后内核更新内核线程对应的进程描述符中的active_mm域,使其指向前一个进程的内存描述符。所以在需要时,内核线程便可以使用前一个进程的页表。因为内核线程不访问用户空间的内存,所以它们仅仅使用地址空间中和内核内存相关的信息。

二、虚拟内存区域

虚拟内存区域VMAs由vm_area_struct结构体描述,vm_area_struct结构体描述了指定地址空间内连续区间上的一个独立内存区域。

三、mmap()和do_mmap():创建地址区间

内核使用do_mmap()函数创建一个新的线性地址区间,do_mmap()函数都会将一个地址区间加入到进程的地址空间中,无论是扩展已存在的内存区域还是创建一个新的区域。

在用户空间可以通过mmap()系统调用获取内核函数do_mmap()的功能。

http://blog.csdn.net/yusiguyuan/article/details/45155035

原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/7126414.html