Linux虚拟存储管理分析

原创 2007年09月12日 09:23:00
Linux虚拟存储管理分析
  要:本文通过解剖Linux操作系统的虚拟存储管理机制,说明了Linux虚拟存储的特点、虚拟存储器的实现方法,并基于Linux Kernel Source 1.0,详细分析有关虚拟存诸管理的主要数据结构之间的关系。
关键字:Linux 操作系统内存管理虚拟存储
 
        Linux操作系统是一种多用户多任务、支持多种平台的开源的类Unix操作系统,其支持多种平台,在服务端可与其它商用类Unix系统媲美,在客户端则向Windows系列发出了强有力的挑战。自Linux诞生以来,发展迅猛,已经受到了全球开源社区和许多商业科技巨头的大力支持以及政府、教育机构、科研单位的重视。本文介绍了Linux虚拟存储技术的特点,并结合操作系统原理和Linux内核源码,通过分析虚拟存储管理所需的主要数据结构及其相互关系,来更深入地了解Linux虚拟存储管理机制。本文所援引的Linux内核源代码版本为1.0
Linux虚拟存储概述
虚拟存储器
          在实存储器的管理模式中,要求作业在运行前全部装入内存,之后就一直驻留在内存中直到运行结束,其中某些程序并没有一直处于运行状态,却长期占用着内存资源,从而降低了内存的利用率,为此,引入了虚拟存储器。
       虚拟存储器并不以物理的方式存在,而是从逻辑上对内存容量进行扩充,提供了一个比真实内存空间大得多的逻辑地址空间的逻辑存储器。虚拟存储技术把用户地址空间和实际的存储空间区分开,在程序运行时通过动态重定位的地址映射机制将逻辑地址转换为物理地址。
       所谓的“动态重定位”是指在目标程序执行过程中,在CPU访问内存之前,由硬件地址映射机构来完成将要访问的指令或数据的逻辑地址向内存的物理地址的转换。由于这种地址转换是在程序执行期间随着每条指令的数据访问自动连续地进行,所以称为“动态重定向”。
       386保护模式下,Linux可以提供的逻辑地址空间为4GBLinux的全局描述符表定义了如何分配逻辑地址空间:0GB – 3GB分配为用户空间,用户进程可以直接访问;3GB – 4GB分配为内核空间,用户进程不能访问。
段页式存储管理
          Linux中的内存管理技术采用的是段页式虚存技术。它将一个进程中的程序、数据、堆栈分成若干“段”来处理,每段有一个8字节的段描述符,指出该段的起始地址、长度和存取权限等信息,这些段描述符的集合构成段描述符表,通过一个寄存器指出该表的起始位置。为了便于段长的动态变化,每段分为若干页,将需要的内容以页面为单位调入内存的物理块中,暂不执行的页面仍留在外存,以保证比实际内存容量需求更大的进程能够正常使用内存。
Linux的分段机制
Linux的分段机制就是将线性地址空间分段,利用这些段来存储代码和数据,通过对段的保护来提供一种对数据或代码的保护。根据每个段的作用和存储内容的不同,分为三类进程段:代码段、数据段和堆栈段;两类系统段:TSS段(任务状态段)和LDT段(局部描述符表段)。
在保护模式下,逻辑地址空间可达4GB。从逻辑地址到线性地址的转换由分段机制管理。段寄存器CSDSESSSFSGS标识一个段。这些段寄存器作为段选择器,用来选择该段的描述符。
       进程使用的是48位的逻辑地址,其中高16位是段选择符,低32位是段内的偏移量。通过段选择符在GDT(全局描述符表)或LDT(局部描述符表)中索引相应的段描述符,以得到该段的基地址,再加上偏移量得到逻辑地址对应的线性地址。然后通过分页地址的转换,将线性地址转换为物理地址,最后通过物理地址访问内存。
       如图1所示,为分段逻辑地址到线性地址的转换图。

1        分段逻辑地址映射到线性地址

Linux的分页机制
分页机制是在段机制之后进行的,它进一步将线性地址转换为物理地址。Linux一般使用4K字节大小的页(PAGE_SIZEinclude/linux/page.h,通过修改PAGE_SHIFT定义的左移位数来修改页面大小),且每页的起始地址都被4K整除。因此,Linux4GB的线性地址空间划分为1M个页面,采用了两级表结构。
两级表的第一级表称为页目录,存储在一个4K字节的页中,页目录表共有1K个表项,每个表项为4个字节,线性地址最高的10位(22-31位)用来产生第一级表索引,由该索引得到的表项中的内容定位了二级表中的一个表的地址,即下级页表所在的内存块号。
第二级表称为页表,存储在一个4K字节页中,它包含了1K字节的表项,每个表项包含了一个页的物理地址。二级页表由线性地址的中间10位(12-21位)进行索引,定位页表表项,获得页的物理地址。页物理地址的高20位与线性地址的低12位形成最后的物理地址。
如图2所示,为两级页表的地址转换图。

2        两级页表转换

 Linux进程与段页式管理
每当启动一个新的进程,Linux都为其创建一个进程控制块(task_struct include/linux/sched.h)。在创建过程中,每个进程(根据需要)创建并初始化新页目录,设置页目录基地址寄存器,在GDT中添加进程对应的TSS项和LDT项,创建并初始化该进程的LDT
Linux采用“按需调页”的原则来分配内存页面,执行进程的页面总会在外存与内存之间不断交换,从而避免页表过多占用存储空间。创建一个进程时页面分配的情况大致是这样的:进程控制块(1页),内存态堆栈(1页),页目录(1页),页表(需要的n页)。在进程以后执行的执行中,再根据需要逐渐分配更多的内存页面。
Linux交换空间
          交换空间是在外存中开辟一定的空间来临时存放从内存中调出的页面,其存储区域自然也是按页划分的。Linux采用了块设备和交换文件两种形式来保存换出的页面,但是这两种形式的内部结构是一致的。有时候,为了优化系统性能,会定义不止1个交换空间,因而Linux实现了并行管理多个交换空间,这些交换空间均定义在同一个数据结构中(swap_info_struct[MAX_SWAPFILES]mm/swap.c,其中MAX_SWAPFILES定义为最大的交换空间数量)。
Linux虚存管理的数据结构模型
Linux虚存管理模型
根据虚拟内存抽象模型,每个进程都可以互不干扰的使用所有虚拟地址。进程的虚拟内存空间被划分为小的虚拟内存区域来使用。每个内存区域是一段具有相同属性的虚拟地址空间。Linuxvm_area_structinclude/linux/mm.h)来描述一个虚拟内存区域。一个进程的所有内存区域组织成一个双向链表。进程用了一个指向vm_area_struct链表的指针,来描述进程虚拟内存空间的一个区域,包括对该区域的起始和终止地址的描述。进程可以通过vm_operation_structinclude/linux/mm.h)对这些区域进行操作。
当加载关于进程虚拟地址空间的页面时,一系列的vm_area_struct将自动生成,每一个vm_area_struct描述进程的一部分,如执行代码、数据等。Linux支持了多数标准的虚拟内存操作,如读取、关闭、共享、缺页等。一旦vm_area_struct结构生成,就可以通过该结构中的指向vm_operation_struct的指针进行虚拟内存操作了。
       如图3所示,为虚存管理数据结构之间的关系。
 
 
3        虚拟存储管理的数据结构关系
数据结构介绍
vm_area_struct
         Linux采用了虚拟存储区域的方式来管理虚拟存储空间,一个虚拟存储区域是某个进程的一段虚拟存储空间,该结构由vm_are_struct定义。
 
struct vm_area_struct {
       struct task_struct * vm_task; /* VM area parameters */
       /* 虚存区的起始地址 */
       unsigned long vm_start;
       /* 虚存区的终止地址 */
       unsigned long vm_end;
       /* 进程对应于虚存区的访问权限 */
       unsigned short vm_page_prot;
       /* linked list,在链表中指向下一个虚拟内存区域*/
       struct vm_area_struct * vm_next;
       /* linked list,在链表中指向共享区域*/
       struct vm_area_struct * vm_share;
       /* 指向虚存区所在文件的inode结构,若不涉及文件,则为NULL */
       struct inode * vm_inode;
       /* 虚存区相对于文件或设备在inode结构中的偏移量 */
       unsigned long vm_offset;
       /* 指向vm_operation_struct结构 */
       struct vm_operations_struct * vm_ops;
};
vm_operation_struct
          Linux对于虚存区的操作定义在vm_operation_struct数据结构中,通过在vm_area_struct结构中使用指针vm_ops来确定该虚存区可以进行的一系列操作。
 
struct vm_operations_struct {
       /* 打开操作,当内核生成一个虚存区后或者当虚存区被复制后,就用该命令打开。*/
       void (*open)(struct vm_area_struct * area);
       /* 关闭操作,当内核销毁一个虚存区时,就调用该命令。*/
       void (*close)(struct vm_area_struct * area);
       /* 处理缺页异常,当进程访问一个不属于内存的有效页面时,就会调用该命令,
    /* 返回该页的物理地址。*/
       void (*nopage)(int error_code,
                     struct vm_area_struct * area, unsigned long address);
       /* 处理写保护异常,当往一个被保护的页面上写入数据时,就会调用该命令。*/
       void (*wppage)(struct vm_area_struct * area, unsigned long address);
       int (*share)(struct vm_area_struct * from, struct vm_area_struct * to, unsigned long address);
       /* 取消映射操作,当内核取消虚存区的部分或者全部映射时,调用该命令;
       /* 当取消全部映射后,内核就会自动调用close()进行关闭操作。*/
       int (*unmap)(struct vm_area_struct *area, unsigned long, size_t);
};
总结
         Linux是一个功能强大的实际的操作系统,相对于操作系统原理,每个技术环节都有其自身的特点。限于篇幅,本文仅简单介绍Linux在虚拟存储管理上的技术特点与实现的数据结构之间的关系,作为深入探讨Linux虚拟存储管理源码细节的入门性文章,希望能起到抛砖引玉的作用。
参考资料
1)Andrew S.TanenbaumModern Operating Systems(Second Edition),机械工业出版社,2002
   (2)Abhishek NayaniMel GormanRodrigo S.de CastroMemory Management in Linux2002
   (3)刘胤杰、岳浩等,Linux操作系统教程,机械工业出版社,2004
 

为你解析Linux虚拟存储管理

Linux操作系统是一种多用户多任务、支持多种平台的开源的类Unix操作系统,其支持多种平台,在服务端可与其它商用类Unix系统媲美,在客户端则向Windows系列发出了强有力的挑战。自Linux诞生...
  • zhangxinrun
  • zhangxinrun
  • 2010年05月18日 17:53
  • 688

Linux 内核源代码情景分析 chap 2 存储管理 (四)

物理页面的使用和周转1. 几个术语1.1 虚存页面指虚拟地址空间中一个固定大小, 边界与页面大小 4KB 对齐的区间及其内容1.2 物理页面与虚存页面相对的, 需要映射到某种物理存储介质上面的页面。 ...
  • zhyh1435589631
  • zhyh1435589631
  • 2016年04月02日 17:20
  • 1145

【数据结构】文件压缩项目

文件压缩的算法思路是基于哈夫曼树的,将字符串文件转换成二进制位存储 heap.h #pragma once #include #include using namesp...
  • shangguan_1234
  • shangguan_1234
  • 2016年10月29日 23:57
  • 1191

linux内核源代码学习(5)内存页面的换入换出

  linux内核源代码学习(5)内存页面的换入换出---flyli       关于物理页面的换入换出,其实其主要的目的也就是当物理内存不够使用的时候,将不常用到的内存页面交换到硬盘上,以保证程序能...
  • flyli_x
  • flyli_x
  • 2009年08月18日 00:16
  • 2118

Linux Swap机制概述

识别需交换的页 1.      页框回收算法(PFRA)将页分为不可回收页、可交换页、可同步页、可丢弃页四种类型。其中,可交换页包括: I.属于进程匿名线性区(如用户态堆、栈)的页; ...
  • wh8_2011
  • wh8_2011
  • 2017年01月26日 09:24
  • 684

linux内核分析-存储器管理-理论篇

  • gao337536127
  • gao337536127
  • 2009年05月12日 13:24
  • 1344

数据结构

数据结构-线性表 1. 线性表:n个数据元素的有序集合。 线性表是一种常用的数据结构。在实际应用中,线性表都是以栈、队列、字符串、数组等特殊线性表的形式来使用的。由于这些特...
  • chinaliping
  • chinaliping
  • 2013年04月12日 15:24
  • 3572

task_struct 数据结构

在linux 中每一个进程都由task_struct 数据结构来定义. task_struct就是我们通常所说的PCB.她是对进程控制的唯一手段也是最有效的手段. 当我们调用fork() 时, 系统会...
  • jiary5201314
  • jiary5201314
  • 2013年05月28日 23:53
  • 291

Linux中的物理和虚拟存储空间布局

在支持MMU的32位处理器平台上,Linux系统中的物理存储空间和虚拟存储空间的地址范围分别都是从0x00000000到0xFFFFFFFF,共4GB,但物理存储空间与虚拟存储空间布局完全不同。Lin...
  • tianyahaijiaozd
  • tianyahaijiaozd
  • 2011年09月17日 11:02
  • 1023

Windows存储管理

Windows存储管理(来源自EMC中文支持论坛) 1.Windows存储管理之磁盘类型简介 各种操作系统连接到存储系统之后,并且操作系统识别物理磁盘之后,需要对磁盘进行进一步配置。如果用...
  • figo829
  • figo829
  • 2013年04月05日 21:25
  • 1578
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux虚拟存储管理分析
举报原因:
原因补充:

(最多只允许输入30个字)