1)每个进程的都有一个task_struct结构体
2)task_struct 包含mm_struct结构体,这个就是进程的内存管理者(内核中的一个数据结构)
3)mm_struct中包含两个链表:rb_vma list_vma,其实都指向该进程的vma链表,只不过组织方式不太一样;
4)vma是什么?https://blog.csdn.net/ywf861029/article/details/6114794
每一个进程都有4G的虚拟地址空间,那么怎么去管理这4G空间内,就是通过内存区域描述:
struct vm_area_struct {
struct mm_struct *vm_mm; /* associated mm_struct */
unsigned long vm_start; /* VMA start, inclusive */
unsigned long vm_end; /* VMA end , exclusive */
struct vm_area_struct *vm_next; /* list of VMA's */
pgprot_t vm_page_prot; /* access permissions */
unsigned long vm_flags; /* flags */
struct rb_node vm_rb; /* VMA's node in the tree */
union { /* links to address_space->i_mmap or i_mmap_nonlinear */
struct {
struct list_head list;
void *parent;
struct vm_area_struct *head;
} vm_set;
struct prio_tree_node prio_tree_node;
} shared;
struct list_head anon_vma_node; /* anon_vma entry */
struct anon_vma *anon_vma; /* anonymous VMA object */
struct vm_operations_struct *vm_ops; /* associated ops */
unsigned long vm_pgoff; /* offset within file */
struct file *vm_file; /* mapped file, if any */
void *vm_private_data; /* private data */
};
当用户进程申请一段地址空间时,可能存在两种情景:
1)如果新申请地址空间跟现有某个vma描述的内存属性线相同,则合并到当前vma中,vma的长度+1
2)如果新申请的地址空间,跟现有的vma没有任何关联,则新创建一个vma
vma的几问:
1)vma是真实的内存地址吗?当然不是,vma只是用来描述当前进程4G空间的使用情况,仅仅是个标记。
2)如果vma并不真实地址,那么用户如何访问到真实的内存?
大致流程是这样的:
1)当进程试图访问某个虚拟地址时,确认该地址空间包含在vma描述的地址范围内,返回虚拟地址空间对应的vma_struct;
2)cpu的mmu单元,首先从cr3寄存器中取出当前进程的页表,然后从页表中找到虚拟地址对应的真实page;
进程的页表一开始是空的,假设page不在进程的页表中怎么办?vm_area_struct结构里面的vm_ops->nopage所指向的函数来将产生缺页异常的地址。
这个地址会不会在进程的页表中标记?应该会吧?而且进程的页表应该会定期删除老数据?