Linux内核用一个task_struct结构描述一个进程,且用current宏表示当前进程的task_struct。
task_struct结构中有一个mm字段,它所指向的便是与该进程虚拟空间(也叫用户空间)所对应的mm_struct结构体。内核正是通过mm_struct结构描述进程的用户空间的。
mm_struct的定义如下:在http://lxr.linux.no/#linux-bk+v2.6.11.5/include/linux/sched.h#L207
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
207 struct mm_struct { 208 struct vm_area_struct * mmap; /* vm_area_struct链表 */ 209 struct rb_root mm_rb; /*指向红黑树*/ 210 struct vm_area_struct * mmap_cache; /* 缓存,指向最近找到的虚拟区间*/ 211 unsigned long (*get_unmapped_area) (struct file *filp, 212 unsigned long addr, unsigned long len, 213 unsigned long pgoff, unsigned long flags); 214 void (*unmap_area) (struct vm_area_struct *area); 215 unsigned long mmap_base; /* base of mmap area */ 216 unsigned long free_area_cache; /* first hole */ 217 pgd_t * pgd; /*指向进程的页目录*/ 218 atomic_t mm_users; /* 用户空间用户数 */ 219 atomic_t mm_count; /* "struct mm_struct" 引用数 */ 220 int map_count; /* number of VMAs */ ...... ...... |
mm_struct 结构是对整个用户空间的描述。一个进程的虚拟空间中有多个虚拟区间(用 vm_area_struct 描述),对这些虚拟区间的组织方式有两种:当虚拟区间较少时采用单链表(由 mmap 指针指向这个链表),当虚拟区间多时采用“红黑树(red_black tree)”结构(由 mm_rb 指向这颗树)。
关于指针 pgd :pgd指向该进程的页目录,每个进程都有自己的页目录。与内核页目录不同,这个页目录进行用户空间 到 物理空间的映射。当调度程序调度一个程序运行时,就将这个地址转成物理地址,并写入CR3寄存器。
关于mm_users和mm_count:简单的说,mm_users用于记录mm_struct结构被多少轻进程(也就是线程)使 用,mm_count记录mm_struct被多少内核线程临时借用(内核线程没有用户空间)。当mm_users为0时,即mm_struct没有被任 何线程使用时,释放 vm_area_struct结构和页表,但不释放mm_struct本身。当mm_count为0时才释放mm_struct。
进程的虚拟空间有多个虚拟区间,每个虚拟区间可能来源不同,有的可能来自可执行文件的执行代码或数据,也可能来自共享库。所以对每个虚拟空间用 vm_area_struct 结构来描述。当执行一个程序时,需将可执行文件映射 到 进程的虚拟地址空间,并产生一组 vm_area_struct 结构来描述。每个 vm_area_struct 结构代表可执行映像的一部分,可能是可执行代码,也可能是数据。
注意:执行一个程序时,可执行文件只是映射到虚拟空间,随着程序的运行,被引用的程序部分会由操作系统装入到物理内存,并同时更新进程的页表。
vm_area_struct定义如下:在http://lxr.linux.no/#linux-bk+v2.6.11.5/include/linux/mm.h#L61
1 2 3 4 5 6 7 8 9 10 |
61 struct vm_area_struct { 62 struct mm_struct * vm_mm; /* The address space we belong to. */ 63 unsigned long vm_start; /* Our start address within vm_mm. */ 64 unsigned long vm_end; /* The first byte after our end address 65 within vm_mm. */ 66 67 /* linked list of VM areas per task, sorted by address */ 68 struct vm_area_struct *vm_next; ...... ...... |
进程用户空间数据结构示意图:图片摘自《深入分析Linux 内核源代码》
我的linux内核游记的下一站是:《fork的那些事》
发表评论
要发表评论,您必须先登录。