Linux内核设计与实现(15)第十五章:进程地址空间

1. 虚拟地址空间

定义:地址空间就是每个进程所能访问的内存地址范围,是一段连续的虚拟内存空间.
	每个进程都有唯一的地址空间,彼此之间互不干扰
	
背景(为什么需要虚拟地址空间?):早期的计算机运行方式是直接将程序运行在物理内存上的三个问题

大小: 4GB大小,有时甚至会超过实际物理内存的大小。

组成:linux下,进程虚拟空间分为:操作系统占1GB,进程占3GB。
	内核空间,栈,动态库,堆,bss段数据,数据段(只读数据段),代码段,保留区域

映射:地址空间最终会通过页表映射到物理内存上,因为内核操作的是物理内存。
	两个映射:
		映射1:建立虚拟空间和可执行文件的映射关系
		映射2:建立虚拟空间的各个页映射到相应的物理地址的映射

内存区域: 可被访问的合法地址空间称为内存区域(memory areas)
	
页错误:当cpu执行进程的某个页面时,发现他要访问的页(虚拟地址的页)没有在物理内存中,而导致的中断(页错误)

详细参考 虚拟地址空间
https://blog.csdn.net/lqy971966/article/details/119378416

2. 内存描述符 mm_struct

2.1 内存描述符 mm_struct

定义:

内存描述符用来表示进程的地址空间,用mm_struct表示

1. start_code、end_code分别表示代码段的起始、结束地址,
2. start_data、end_data分别表示数据段的起始、结束地址,
3. mm_struct通过allocate_mm()宏从slab缓存中分配得到。
4. 在进程描述符task_struct中,mm域存放该进程的内存描述符
5. 内核线程没有进程地址空间,也没有相关的内存描述符
	所以内核线程对应的进程描述符中mm域为空。内核线程不需要访问任何用户空间的内存。

内部的mmap和mm_rb两个数据结构表示的内容一样,此处做了冗余。
前者为链表,便于高效遍历所有;后者为红黑树,便于高效搜索

2.2 内核线程没有进程地址空间

对Linux来说,用户进程和内核线程都是 task_struct 的实例,
唯一的区别是内核线程是没有进程地址空间的(内核线程使用的内核地址空间)。
内核线程的mm描述符是NULL,即内核线程的tsk->mm域是空(NULL)。

2.3 进程是用户进程还是内核线程

内核调度程序在进程上下文的时候,会根据tsk->mm判断即将调度的进程是用户进程还是内核线程。
但是虽然内核线程不用访问用户进程地址空间,但是仍然需要页表来访问内核自己的空间。
而对任何用户进程来说,他们的内核空间都是100%相同的,

所以内核会借用上一个被调用的用户进程的mm_struct中的页表来访问内核地址,这个mm_struct就记录在active_mm。
简而言之就是,对于内核线程,tsk->mm == NULL表示自己内核线程的身份,
而tsk->active_mm是借用上一个用户进程的mm_struct,用mm_struct的页表来访问内核空间。
对于用户进程,tsk->mm == tsk->active_mm。

3. 分配进程地址空间(直接用GFP_ATOMIC,不用GFP_KERNEL)

参考 kernel/fork.c 中的宏 allocate_mm
#define allocate_mm()    (kmem_cache_alloc(mm_cachep, GFP_KERNEL))
#define free_mm(mm)    (kmem_cache_free(mm_cachep, (mm)))

详细接口参考:
Linux内存管理之slab 2:slab API
https://blog.csdn.net/lqy971966/article/details/119801912

分配进程地址空间时,都是从slab高速缓存中分配的

[root@localhost home]# cat /proc/slabinfo | grep mm_struct
mm_struct             60     60   1600   20    8 : tunables    0    0    0 : slabdata      3      3      0
[root@localhost home]#

4. 虚拟内存区域(VMA)

内存区域在linux中也被称为虚拟内存区域(VMA),它其实就是进程地址空间上一段连续的内存范围。

struct vm_area_struct {		//linux/mm_types.h

5. 地址空间和页表

5.1 页表:

地址空间中的地址都是虚拟内存中的地址,而CPU需要操作的是物理内存,所以需要一个将虚拟地址映射到物理地址的机制。
这个机制就是页表。

地址的转换工作需要通过查询页表才能完成:

将虚拟地址分段,使每段虚拟地址都作为一个索引指向页表,而页表项则指向下一级别的页表或指向最终的物理页面。

5.2 3级页面(PGD PMD PTE)

linux中使用3级页面来完成虚拟地址到物理地址的转换。

1. PGD - 全局页目录,包含一个 pgd_t 类型数组,多数体系结构中 pgd_t 类型就是一个无符号长整型
2. PMD - 中间页目录,它是个 pmd_t 类型数组
3. PTE - 简称页表,包含一个 pte_t 类型的页表项,该页表项指向物理页面

图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/lqy971966/article/details/119806133