【www.arisingsemi.com--IT认证】

schedul
第四章 Linux存储管理
Linux操作系统采用了请求式分页虚拟存储管理方法。 系统为每个进程提供了4GB的虚拟内存空间。各个进程的虚拟内存彼此独立。
§4.1  进程虚存空间的管理
一.内核空间和用户空间
● 进程运行时能访问的存储空间只是它的虚拟内存空间。
对当前该进程而言只有属于它的虚拟内存是可见的。
● 在进程的虚拟内存包含着进程本身的程序代码和数据。

● 进程在运行中还必须得到操作系统的支持。进程的虚拟内存中还包含着操作系统内核。

● Linux把进程的虚拟内存分成两部分,内核区和用户区。
● 操作系统内核的代码和数据等被映射到内核区。

● 进程的可执行映像(代码和数据)映射到虚拟内存的用户区。
● 进程虚拟内存的内核区的访问权限设置为0级,用户区为3级。

● 内核访问虚存的权限为0级,而进程的访问权限为3级
Linux运行在x86时,进程的虚拟内存为4GB。
进程虚存空间的划分在系统初始化时由GDT确定,
它定义在/arch/i386/kernel/head.S文件中:
.quad 0x0000000000000000    /* NULL 描述符 */
.quad 0x0000000000000000    /* 未使用*/
.quad 0xc0c39a000000ffff    /* 内核代码段1GB在0xc0000000 */
.quad 0xc0c392000000ffff    /* 内核数据段1GB在0xc0000000 */
.quad 0x00cbfa000000ffff    /* 用户代码段3GB在0x00000000 */
.quad 0x00cbf2000000ffff    /* 用户数据段3GB在0x00000000 */
.quad 0x0000000000000000    /* 未使用 */
.quad 0x0000000000000000    /* 未使用 */
.fill 2*NR_TASKS,8,0        /* 各个进程LDT描述符和TSS描述符的空间 */
Linux的存储管理主要是管理进程虚拟内存的用户区。

进程虚拟内存的用户区分成代码段、数据段、堆栈
以及进程运行的环境变量、参数传递区域等。
每一个进程,用一个mm_struct结构体来定义它的虚存用户区。
mm_struct结构体首地址在任务结构体task_struct成员项mm中:
struct mm_struct  *mm;
mm_struct结构定义在/include/linux/schedul.h中。
pgd 为指向进程页目录表的指针。
context 是进程上下文的地址。
start_code, end_code, start_data, end_data
分别为代码段、数据段的首地址和终止地址。

start_stack 是进程堆栈的首地址。
arg_start, arg_end, env_start, env_end
分别为参数区、环境变量区的首地址和终止地址。
二.进程的虚存区域
一个虚存区域是虚存空间中一个连续的区域,在这个区域中的信息具有相同的操作和访问特性。每个虚拟区域用一个vm_area_struct结构体进行描述.它定义在/include/linux/mm.h中:


(1)vm_mm指针指向进程的mm_struct结构体。



(2)vm_start和vm_end 虚拟区域的开始和终止地址。



(3)vm_flags指出了虚存区域的操作特性:
VM_READ                虚存区域允许读取
VM_WRITE                虚存区域允许写入
VM_EXEC              虚存区域允许执行
VM_SHARED            虚存区域允许多个进程共享
VM_GROWSDOWN    虚存区域可以向下延伸
VM_GROWSUP          虚存区域可以向上延伸
VM_SHM            虚存区域是共享存储器的一部分
VM_LOCKED            虚存区域可以加锁
VM_STACK_FLAGS 虚存区域做为堆栈使用


(4)vm_page_prot 虚存区域的页面的保护特性。


(5)若虚存区域映射的是磁盘文件或设备文件的的内容,则vm_inode指向这个文件的inode结构体,否则vm_inode为NULL。



(6)vm_offset是该区域的内容相对于文件起始位置的偏移量,或相对于共享内存首址的偏移量。


(7)所有vm_area_struct结构体链接成一个单向链表,vm_next指向下一个vm_area_struct结构体。链表的首地址由mm_struct中成员项mmap指出。



(8)vm_ops是指向vm_operations_struct结构体的指针。该结构体中包含着指向各种操作的函数的指针。



(9)所有vm_area_struct结构体组成一个AVL树。

(Adelson-Velskii and Landis)
AVL树是一种具有平衡结构的二叉树。
vm_avl_left 左指针指向相邻的低地址虚存区域,
vm_avl_right右指针指向相邻的高地址虚存区域
mmap_avl    表示进程AVL树的根,
vm_avl_hight表示AVL树的高度。



(10)vm_next_share和vm_prev_share,把有关的vm_area_struct
结合成一个共享内存时使用的双向链表。

§4.2  虚存空间的映射和虚存区域的建立
一.虚拟空间的地址映射
在多进程操作系统中,同时运行多个用户的程序,系统分配给用户的物理地址空间放不下代码和数据等。为了解决这个矛盾而出现了虚拟存储技术.在虚拟存储技术中,用户的代码和数据(可执行映像)等并不是完整地装入物理内存,而是全部映射到虚拟内存空间。
在进程需要访问内存时,在虚拟内存中“找到”要访问的程序代码和数据等。
系统再把虚拟空间的地址转换成物理内存的物理地址。

二.虚存区域的建立
Linux使用do_mmap()函数完成可执行映像向虚存区域的映射,
由它建立有关的虚存区域
do_mmap()函数定义在/mm/mmap.c文件中
addr虚存区域在虚拟内存空间的开始地址,
len是这个虚存区域的长度。
file是指向该文件结构体的指针,
off是相对于文件起始位置的偏移量。
若file为NULL,称为匿名映射(anonymous mapping)。
prot指定了虚存区域的访问特性:
PROT_READ   0x1  对虚存区域允许读取
PROT_WEITE  0x2  对虚存区域允许写入
PROT_EXEC   0x4  虚存区域(代码)允许执行
PROT_NONE   0x0  不允许访问该虚存区域
flag指定了虚存区域的属性:
MAP_FIXED  指定虚存区域固定在addr的位置上。

MAP_SHARED 指定对虚存区域的操作是作用在共享页面上 
MAP_PRIVATE指定了对虚存区域的写入操作将引起页面拷贝。
§4.3 Linux的分页式存储管理
一. Linux的三级分页结构
● 页表是从线性地址向物理地址转换中不可缺少的数据结构,而且它使用的频率较高。页表必须存放在物理存储器中。
● 虚存空间有4GB,按4KB页面划分页表可以有1M页。

若采用一级页表机制,页表有1M个表项,每个表项4字节,
这个页面就要占用4MB的内存空间。
● 由于系统中每个进程都有自己的页表,如果每个页表占用4MB,
对于多个进程而言就要占去大量的物理内存,这是不现实的。
● 在目前用户的进程不可能需要使用4GB这么庞大的虚存空间,
若使用1M个表项的一级页表,势必造成物理内存极大的浪费。

● 为此,Linux采用了三级页表结构,以利于节省物理内存。
● 三级分页管理把虚拟地址分成四个位段:。

本文来源:http://www.arisingsemi.com/it/84050/