操作系统内存管理-01分段

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统内存管理-01分段相关的知识,希望对你有一定的参考价值。

前言

本文讲述本文博主在学习80386window下段式内存管理。

内存管理往往需要软硬件结合进行管理,CPU定制一套官方规范,要求操作系统按要求实现某些操作即可。本文所述的CPU 分段规范 在intel 第三卷 第三章。

分段概述

我们知道每一个程序会被赋予一个"虚拟内存",在进行实际对内存写入的时候会进行一次转物理地址转化在进行操作。

下图在来自intel手册,这个转化分为两个部分:段地址转化线性地址(分段机制),线性地址通过页表转化物理地址(分页机制)。

当然分页机制intel并没有做强制要求开启,但是分段逻辑被强制开启了。分页逻辑没有开启那么分段逻辑转化的线性地址就是物理地址。

intel把内存划分很多个区域每个区域我们把它视为一个段,


将虚拟内存的段转化为物理的段地址。

每个段都有相关可读可写等属性,这些属性被放入一个叫 段描述符(segment descriptor) 的数据结构中,并且数据结构还承担虚拟内存中的段转化为物理地址中段地址。


段描述表一般存于两个寄存器中GDTRLDTR。并且这两个寄存器存放的是直接物理地址中的表位置,不然的话会产生先有鸡还是现有蛋问题。

我们可以用windbg调试内核输出相关寄存器

//windbg相关命令
//查看 gdtr寄存器
r gdtr
//查看 ldtr寄存器
l ldtr
//查看当前处理器信息 https://en.wikipedia.org/wiki/Processor_Control_Region
!pcr


我们可以使用dd命令单独查看这个指向的地址数据

或者使用dg 查看解析后的段描述符号结果

一些可视化工具的输出

看了上面的数据后我们看看段选择子(segment selector)概念。我们知道GDTR存储一个表,里面有很多段描述符,而一个程序里面有很多段我怎么知道这个段跟哪个段描述符相关呢?这关系映射又是靠一个段选择子的数据结构维护的。段选择子必须加载到一个段寄存器中才能使用(这也导致了使用段机制一些缺陷,所以很多操作系都弱化了段的其中一个原因)。

系统预置的段寄存器如下:
CS SS DS ES FS GS

他们存储的数据结构可以存储了相关GDTR表中索引,当然为了加速intel在这些寄存器末尾额外补充了一个64长度的数据用于缓存段描述符(也是64位),当然这部分存储空间对开发者不可见。也有称为影子寄存器或者称为段寄存器不可见部分。


上图来自intel手册。visible part 大小为16位也就是程序员可以操作的,hidden part就是影子寄存器。

其数据结构如下:

第0位-第1位 作为权限位 用于权限请求位。
第2位 表示你要去GDTR 还是LDTR查找表。
第15-3位 作为GDT的下标,一共13位共计8192项。

举个例子:

我们距离如下三个段选择子:
cs=0008
ss=0010
ds=0023


void printSegmentSelector(int16_t ss) 

	int index =ss>>3;
	int TI =ss>>2 & 0x1;
	int PRL = 0x3 & ss;

	char out[100] =  0 ;
	sprintf_s(out, "index=[%d] ti = [%d] prl=[%d]", index, TI, PRL);
	printf("%s\\r\\n", out);

int main()

	
	

	printSegmentSelector(0x0008);
	printSegmentSelector(0x0010);
	printSegmentSelector(0x0023);
	return 0;

	

输出
index=[1] ti = [0] prl=[0]
index=[2] ti = [0] prl=[0]
index=[4] ti = [0] prl=[3]

我们使用dg命令去查看对应段描述符解析结果

可见这三个段的范围是0-4G 也就是整个内存,可见分段已经被弱化。

段描述符

数据结构是一个64位大小,如下图所示(来自itnel手册)

重要字段:
Base Address: 32位的基地址,由描述符的三个部分组成(由于历史因素要向后兼容才会将其分散)。
Segment Limit: 20位的段内偏移,由描述符的两个部分组成(由于历史因素要向后兼容才会将其分散)。
G :设置Segment Limit 粒度是字节为单位还是4kb为单位,1为4kb

我们假设G为 4k为单位那么Segment Limit偏移大小就是0到4G。

这里我们直接使用pchunter查看解析结果即可

参考链接

现代操作系统内存管理到底是分段还是分页,段寄存器还有用吗?

what-is-the-difference-between-linear-physical-logical-and-virtual-memory-addr

how-are-segment-registers-involved-in-memory-address-translation

GDT_Tutorial

内核_段寄存器|段描述符|段选择子(详解)

Linux 获取虚拟地址对应的物理地址

以上是关于操作系统内存管理-01分段的主要内容,如果未能解决你的问题,请参考以下文章

操作系统内存管理-01分段

操作系统 内存管理 分页/分段/段页式管理

小林coding阅读笔记:操作系统篇之内存管理基础,虚拟内存分段分页

小林coding阅读笔记:操作系统篇之内存管理基础,虚拟内存分段分页

操作系统-3.5-内存(基本分段存储管理&&段页式管理)

20.内存换入-请求调页