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)在段寄存器(16位选择器)中装入段选择符,同时把32位地址偏移量装入某个寄存器(比如ESI、EDI等)中。
(2)根据选择符中的索引值、TI及RPL值,再根据相应描述符表中的段基地址和段界限,进行一系列合法性检查(如特权级检查、界限检查),如果该段无问题,就取出相应的描述符放入段描述符高速缓冲寄存器中。
(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-陈莉君
Linux内存管理2---段机制的更多相关文章
- Linux内存管理3---分页机制
1.前言 本文所述关于内存管理的系列文章主要是对陈莉君老师所讲述的内存管理知识讲座的整理. 本讲座主要分三个主题展开对内存管理进行讲解:内存管理的硬件基础.虚拟地址空间的管理.物理地址空间的管理. 本 ...
- [转帖]Linux分页机制之概述--Linux内存管理(六)
Linux分页机制之概述--Linux内存管理(六) 2016年09月01日 19:46:08 JeanCheng 阅读数:5491 标签: linuxkernel内存管理分页架构更多 个人分类: ┈ ...
- 浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多?在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在这 ...
- 了解linux内存管理机制(转)
今天了解了下linux内存管理机制,在这里记录下,原文在这里http://ixdba.blog.51cto.com/2895551/541355 根据自己的理解画了张图: 下面是转载的内容: 一 物理 ...
- [转帖]Linux分页机制之分页机制的演变--Linux内存管理(七)
Linux分页机制之分页机制的演变--Linux内存管理(七) 2016年09月01日 20:01:31 JeanCheng 阅读数:4543 https://blog.csdn.net/gatiem ...
- 【转载】Linux 内存管理机制
在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,主要特点是,无论物理内存有多大,Linux 都将其充份利用,将 ...
- Linux内存管理Swap和Buffer Cache机制
Linux内存管理Swap和Buffer Cache机制 一个完整的Linux系统主要有存储管理,内存管理,文件系统和进程管理等几方面组成,贴出一些以前学习过的一个很好的文章.与大家共享!以下主要说明 ...
- Linux内存管理机制简析
Linux内存管理机制简析 本文对Linux内存管理机制做一个简单的分析,试图让你快速理解Linux一些内存管理的概念并有效的利用一些管理方法. NUMA Linux 2.6开始支持NUMA( Non ...
- 【转载】浅谈Linux内存管理机制
经常遇到一些刚接触Linux的新手会问内存占用怎么那么多? 在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然.这是Linux内存管理的一个优秀特性,在 ...
随机推荐
- Leetcode 237.删除链表中的节点 By Python
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点. 现有一个链表 -- head = [4,5,1,9],它可以表示为: 4 -> 5 -> 1 - ...
- [CF791D]Bear and Tree Jumps
题目描述 A tree is an undirected connected graph without cycles. The distance between two vertices is th ...
- SharePoint 2013 Central Admin 不能打开
当我准备打开CA时发现下面的错误: This operation can be performed only on a computer that is joined to a server farm ...
- 【翻译】go memory model
https://studygolang.com/articles/819 原文链接 Introduction The Go memory model specifies the conditions ...
- 几个面试经典算法题Java解答
题目一: public class testClockwiseOutput { //顺时针打印一个矩阵 @Test public void test(){ int[][] num = new int[ ...
- 【模板】Splay
Splay 均摊复杂度证明见此处 \(\rightarrow\) 链接 代码如下 #include <bits/stdc++.h> using namespace std; const i ...
- 费马定理&欧拉定理
费马定理: ap≡a(mod p) 其中p为质数,且a不是p的倍数 证明: ..... 欧拉定理: aφ(p)≡1(mod p) φ(x)(欧拉函数)为小于等于x且与x互质的数的个数 φ(x)=∏(p ...
- 数据类型、位运算、sizeof()函数
数据精度,依次升高.(负数必须使用有符号类型) 不同精度的数据间运算,所得结果为高精度类型. 数据类型详细信息如下图: 整型数据的数制:十进制(32).八进制(032,以0开头).十六进制(0x32, ...
- Scala进阶之路-进程控制之执行shell脚本
Scala进阶之路-进程控制之执行shell脚本 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 废话不多说,我这里直接放一个案例. /* @author :yinzhengjie ...
- Linux上安装Perl模块的两种方法
Linux/Unix下安装Perl模块有两种方法:手工安装和自动安装.第一种方法是从CPAN上下载 您需要的模块,手工编译.安装.第二种方法是联上internet,使用一个叫做CPAN的模块自动完 ...