Linux内存管理2---段机制

1.前言

本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理。

本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础、虚拟地址空间的管理、物理地址空间的管理.

本文将主要以X86架构为例来介绍Linux内存管理的段机制。

2.段机制

  • 段是虚拟地址空间的基本单位
  • 段机制必须把虚拟地址空间的一个地址转换为线性地址空间的一个线性地址
  • 可以从三个方面来描述段(如下图)

段的基地址(Base):在线性地址空间中段的起始地址;

段的界限(Limit):在虚拟地址空间中,段内可以使用的最大偏移量;

段的保护属性:表示段的特性。例如该段是否可以被读出或写入。或者该段是否可以作为一个程序来执行,以及段的特权等级

图 段描述符的一般格式

  • 段描述符表

图 段描述符表(段表)

段号描述虚拟地址空间段的编号;基地址是线性地址空间段的起始地址

  • 保护模式下其它描述符表

全局描述符表(GDT)

中断描述符表(IDT)

局部描述符表(LDT)

注:为加快对如上描述符表的访问,intel为之设计了专门的寄存器,存放描述符表的基地址及表的长度界限

  • 保护模式下的段寄存器

段寄存器存放段描述符表的索引(段号,也叫选择符),即从段描述符表中选择某个段.

其中:

索引(13位指明段号);

TI(Table Index)指明使用全局描述符表还是局部描述符表;

RPL(Requestor Previlege Level):2位指定4种特权级,用来决定内核态还是用户态

图 保护模式下的段寄存器

  • 保护模式下的特权级

保护模式提供了四个特权级,用0~3四个数字表示

一般操作系统只使用了其中最低和最高两个,即0表示最高特权级,内核态;3表示最低特权级,用户态

保护模式规定高特权级可随意访问低特权级,低特权级不能随便访问高特权级

  • 地址转换及保护

图 地址转换

程序中的虚拟地址可以表示为“选择符:偏移量”这样的形式,通过以下步骤可以把一个虚拟地址转换为线性地址:

  (1)在段寄存器中装入段选择符,同时把32位地址偏移量装入某个寄存器(比如ESI、EDI等)中。

  (2)根据选择符中的索引值、TI及RPL值,再根据相应描述符表中的段基地址和段界限,进行一系列合法性检查(如特权级检查、界限检查),如果该段无问题,就取出相应的描述符放入段描述符高速缓冲寄存器3中。

  (3)将描述符中的32位段基地址和放在ESI、EDI等中的32位有效地址相加,就形成了32位线性地址。

  注意,在上面的地址转换过程中,从两个方面对段进行了保护:

  (1) 在一个段内,如果偏移量大于段界限,虚拟地址将没有意义,系统将产生异常。

  (2) 如果要对一个段进行访问,系统会根据段的保护属性检查访问者是否具有访问权限,如果没有,则产生异常。例如,如果要在只读段中进行写入,系统将根据该段的属性检测到这是一种违规操作,则产生异常。

3.Linux如何处理段

Linux将整个虚拟地址空间划分为一个段,段的基地址为0,段的界限为4G。

由于很多体系结构并不要求段机制必选,因此这样处理即使用了段机制又巧妙的化解了段机制

  • IA32上设计操作系统时无法回避使用段机制

在IA32上任意给出的地址都是一个虚拟地址,即任意一个地址都是通过“选择符:偏移量”的方式给出的,这是段机制存访问模式的基本特点

所以在IA32上设计操作系统时无法回避使用段机制,IA32规定段机制是不可禁止的,因此不可能绕过它直接给出线性地址空间的地址

一个虚拟地址最终会通过“段基地址+偏移量”的方式转化为一个线性地址

  • 为何要绕过段机制

由于绝大多数硬件平台都不支持段机制,只支持分页机制,所以为了让Linux具有更好的可移植性,我们需要去掉段机制而只使用分页机制

  • Linux如何绕过段机制 

Linux的设计人员干脆让段的基地址为0,而段的界限为4GB,这时任意给出一个偏移量,则等式为“0+偏移量=线性地址”,也就是说“偏移量=线性地址”。

另外由于段机制规定“偏移量 <4GB”,所以偏移量的范围为0H~FFFFFFFFH,这恰好是线性地址空间范围,也就是说虚拟地址直接映射到了线性地址,

我们以后所提到的虚拟地址和线性地址指的也就是同一地址。

看来,Linux在没有回避段机制的情况下巧妙地把段机制给绕过去了。

  • Linux所必须创建哪些段  

由于IA32段机制还规定,必须为代码段和数据段创建不同的段,所以Linux必须为代码段和数据段分别创建一个基地址为0,段界限为4GB的段描述符。

不仅如此,由于Linux内核运行在特权级0,而用户程序运行在特权级别3,根据IA32的段保护机制规定,特权级3的程序是无法访问特权级为0的段的,所以Linux必须为内核和用户程序分别创建其代码段和数据段。

这就意味着Linux必须创建4个段描述符——特权级0的代码段和数据段,特权级3的代码段和数据段。

  • Linux通过分页机制来保护内存  

如果这么定义段,则上一节所说的段保护的第一个作用就失去了,因为这些段使用完全相同的线性地址空间(0~4GB),它们互相覆盖。

可以设想,如果不使用分页的话,线性地址空间直接被映射到物理空间,则你修改任何一个段的数据,都会同时修改其它段的数据

段机制所提供的通过“基地址:界限”方式本来将线性地址空间分割,以让段与段之间完全隔离,这种实现段保护的方式根本就不起作用了。

那么,这是不是意味着用户可以随意修改内核数据?显然不是的,这是因为,一方面用户段和内核段具有不同的特权级别,另一方面,Linux之所以这么定义段,正是为了实现一个纯的分页,而分页机制会提供给我们所需要的保护。

4.参考文献

[1] Linux内存管理讲座PPT-陈莉君

时间: 2024-11-05 03:24:58

Linux内存管理2---段机制的相关文章

Linux内存管理3---分页机制

1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本文将主要以X86架构为例来介绍Linux内存管理的分页机制. 2.分页机制 5. Linux中的汇编 6.Linux系统地址映射示例

Linux内存管理机制

一.首先大概了解一下计算机CPU.Cache.内存.硬盘之间的关系及区别. 1.  CPU也称为中央处理器(CPU,Central Processing Unit)是一块超大规模的集成电路, 是一台计算机的运算核心(Core)和控制核心( Control Unit).它的功能主要是解释计算机指令以及处理计算机软件中的数据.中央处理器主要由三核心部件组成,运算器.控制器和总线(BUS),运算器又主要由算术逻辑单元(ALU)和寄存器(RS)组成. 2.Cache即高速缓冲存储器,是位于CPU与主内存

浅谈Linux内存管理机制

经常遇到一些刚接触Linux的新手会问内存占用怎么那么多? 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这方面,区别于Windows的内存管理.主要特点是,无论物理内存有多大,Linux 都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能.而Windows是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间.换句话说,每增加一

[转帖]Linux分页机制之分页机制的演变--Linux内存管理(七)

Linux分页机制之分页机制的演变--Linux内存管理(七) 2016年09月01日 20:01:31 JeanCheng 阅读数:4543 https://blog.csdn.net/gatieme/article/details/52402967 ~ 版权声明:本文为博主原创文章 && 转载请著名出处 @ http://blog.csdn.net/gatieme https://blog.csdn.net/gatieme/article/details/52402967 日期 内核版

Linux内存管理机制简介

在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,区别于 Windows的内存管理. 主要特点是,无论物理内存有多大,Linux 都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能.而Windows 是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间.换句话说,Linux自身的预分配内存机制使得主机上的物理内存会全部被用上.每增加一

【研究任务】linux内存管理机制——内核空间

Linux内存中线性地址为4G,0~3G为用户空间,3~4G为内核空间 一.      内核空间 内核空间是3~4G的内存地址,主要用来存储高优先级的代码 在X86结构中的内核地址存在三种类型的区域: ZONE_DMA     内存开始的16m ZONE_NORMAL       16m~896m ZONE_HIGHMEM    896M~ ZONE_DMA是DMA使用的页(DMA是直接路径访问,不经过cpu缓存而直接访问内存)ZONE_NORMAL是正常可寻址的页.ZONE_HIGHMEM是动

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Linux内存管理 【转】

转自:http://blog.chinaunix.net/uid-25909619-id-4491368.html Linux内存管理 摘要:本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法.力求从外到内.水到渠成地引导网友分析Linux的内存管理与使用.在本章最后,我们给出一个内存映射的实例,帮助网友们理解内核内存管理与用户内存管理之间的关系,希望大家最终能驾驭Linux内存管理. 前言 内存管理一向是所有操作系统书

linux内存管理浅析

[地址映射](图:左中)linux内核使用页式内存管理,应用程序给出的内存地址是虚拟地址,它需要经过若干级页表一级一级的变换,才变成真正的物理地址.想一下,地址映射还是一件很恐怖的事情.当访问一个由虚拟地址表示的内存空间时,需要先经过若干次的内存访问,得到每一级页表中用于转换的页表项(页表是存放在内存里面的),才能完成映射.也就是说,要实现一次内存访问,实际上内存被访问了N+1次(N=页表级数),并且还需要做N次加法运算.所以,地址映射必须要有硬件支持,mmu(内存管理单元)就是这个硬件.并且需