段表和页表【转】

本文涉及的产品
公网NAT网关,每月750个小时 15CU
简介:

转自:http://www.cnblogs.com/worldisimple/articles/2447577.html

一、概述处理器(CPU

1.1 处理器位数

在intel处理器的X86系列中,包含8086和8088的16位处理器,以及从80386(即i386)开始的32位处理器,而如今又有X86-64架构的64位处理器。

那这些16位,32位和64位又有什么意义了?位数越高,处理器的寻址能力越强,则可以支持越大的物理内存。具体如下表(可见对于64位处理器的寻址范围已经是非常之大):

处理器位数

可支持的物理内存大小

寻址范围

16

2^16 = 64K

0x0000 ~ 0xffff

32

2^32 = 4G

0x00000000 ~ 0xffffffff

64

2^64

 

在平时安装操作系统时候,经常会问是要装32位系统还是64位系统?对于32位处理器,只能安装32位的系统,不能安装64位系统。对于64位处理,既能够安装32位的系统,也可以安装64位的系统。在Linux下可以通过下面的方面查询系统装的是几位的:

(1) 查看根目录下是否有有lib64目录。32位系统只有/lib一个目录,64位的系统会有/lib64和/lib两个目录。

(2) 执行getconf LONG_BIT命令查看返回结果。32位的系统中long类型是4字节(32位),64位的系统中long类型已变成了8字节(64位)。

(3) 执行uname -i命令。32位的系统返回i386,64位的系统放回x86_64

(4) 执行file /bin/ls命令。

32位系统返回如下结果:

/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5,dynamically linked (uses shared libs), stripped

64位系统返回如下结果:

/bin/ls: ELF 64-bit LSB executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.6.9,dynamically linked (uses shared libs), for GNU/Linux 2.6.9, stripped

1.2 处理器的寄存器

寄存器是处理器的组成部分,是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。寄存器的访问速度在所有存储阶层(见下图)是最快的。

在大学学习汇编时候,还用寄存器来写汇编程序,现在也忘记差不多了,这边就大致记录一下处理器分别有哪些寄存器。

在8086中,所有的寄存器都是16位的。

在80386中,寄存器的发生的变化如下:

(1) 把16位的通用寄存器、指令指针寄存器以及标志寄存器扩充为32位的寄存器。

(2) 段寄存器仍然为16位,并增加2个16位的段寄存器。

寄存器的分类

32CPU寄存器

16CPU寄存器

主要用途

数据

寄存器

EAX

AX

乘、除运算,字的输入输出,中间结果的缓存

EBX

BX

存储器指针

ECX

CX

串操作、循环控制的计数器

EDX

DX

字的乘、除运算,间接的输入输出

变址

寄存器

ESI

SI

存储器指针、串指令中的源操作数指针

EDI

DI

存储器指针、串指令中的目的操作数指针

变址

寄存器

EBP

BP

存储器指针、存取堆栈的指针

ESP

SP

堆栈的栈顶指针

指令指针寄存器

EIP

IP

存放下一条将要执行指令的偏移量,偏移量加上当前代码段的基地址,就形成了下一条指令的地址。

标志位寄存器

EFLAG

FLAG

 

段寄存器

CS

CS

代码段寄存器

DS

DS

数据段寄存器

SS

SS

堆栈段寄存器

ES

ES

附加数据段寄存器

FS

-

32CPU新增加的附加数据段寄存器

GS

-

32CPU新增加的附加数据段寄存器

(3) 增加4个32位的控制寄存器(CR0、CR1、CR2 和CR3),在进程管理及虚拟内存管理中会涉及到CR0(其中有2位分别用于指示运行在实模式/保护模式和是否开启分页机制)、CR2以及CR3(是页目录基址寄存器,保存页目录表的物理地址)这几个寄存器。

(4) 增加4个系统地址寄存器,具体如下:

全局描述符表寄存器GDTR(Global Descriptor Table Register),是48位寄存器,用来保存全局描述符表(GDT)的32位基地址和16位GDT的界限。

中断描述符表寄存器IDTR(Interrupt Descriptor Table Register),是48位寄存器,用来保存中断描述符表(IDT)的32位基地址和16位IDT的界限。

局部描述符表寄存器LDTR(Global Descriptor Table Register),是16位寄存器,保存局部描述符表LDT段的选择符。

任务状态寄存器TR(Task State Register)是16位寄存器,用于保存任务状态段TSS段的16位选择符。

(5) 增加8个32位调式寄存器DR0~DR7

(6) 增加2个32位测试寄存器TR6和TR7

 

二、内存管理

 

下面的内容主要依赖于80386的32位处理器的保护模式下。

2.1 内存地址

物理内存单元的实际地址即物理地址。32位的处理器寻址范围为0x00000000 ~ 0xffffffff,支持4G的物理内存大小。

程序产生的段选择符与段相关的偏移地址部分构成了逻辑地址。在实模式下,没有分段或分页机制,逻辑地址和物理地址是相等的,不需要地址转换可以直接访问物理内存。但是在保护模式下,逻辑地址需要转换成物理地址,才能访问物理内存。那么,这个时候需要处理器中的内存管理单元(MMU)将逻辑地址映射为物理地址,来进行地址转换(如下图)。

那么,MMU是怎么将逻辑地址转换成物理地址?

MMU是一种硬件电路,它包含两个部件,一个是分段部件,一个是分页部件,通过分段机制(把一个逻辑地址转换为线性地址,线性地址也是32位,其地址取值范围为0x00000000~0xffffffff)和分页机制(把一个线性地址转换为物理地址),最终将逻辑地址映射为物理地址。如下图:

2.2 分段机制

在操作系统原理关于分段的说明:段的分配时为了更好的满足用户,段的长度不固定,由用户定义,每个段都有自己的地址空间(通过基址包含某物理内存的地址,和长度值来表示段的长度),表示一个地址需要给出段部分(选择符)和偏移部分。如下图,如果没有分页的话,那么图中的线性地址也就是物理地址,这种方式对于段的离散分配就很容易导致碎片问题(进而使用分页机制来提高内存利用率):

在Linux中,主要设置了:内核代码段,内核数据段,用户代码段,用户数据段。而且每个段的基地址对应线性地址都是为0,而且都可以使用4G的地址空间,相当与绕过了逻辑地址和线性地址的映射,从而完全利用了分页机制。另外,分段中怎样使用段寄存器可以参考:http://book.51cto.com/art/200812/103305.htm

2.3 分页机制

通过使用分页机制可以很好的提高内存利用率。分页机制把一个线性地址转换为物理地址。Linux下一个页大小为4K,把线性地址(32位)和物理地址(32位,2^32=4G物理内存)都按照4K(2^12)页大小来进行划分,那么,一共有4G/4K=1M的页面,如果只是简单的进行线性地址和物理地址一对一记录映射的话,这样在映射表建立的就会占用比较大的物理内存。这个时候就引入了页表页目录表,地址转换过程见下图:

(1) 通过对32位线性地址划分:第31~22这10位(2^10=1024)定位页目录项,第21~12这10位定位页表项,第11~0这12位(2^12=4K)为页内偏移值。

(2) 对于页目录表,有1024个页目录项,每个页目录项(又含有1024个页表项)指向下一级页表的物理地址(32位=4个字节),那么一共需要1024*4(=4K)字节,即只要分配一页就可以完全存放。

(3) 对于页表,原理和页目录表一样,那么一共需要1024(1024个页目录项)*1024(每个页目录项含有1024个页表项)*4(=1M)字节。

(4) 对于页目录的物理地址,就存放在CR3寄存器中。

所以,这样可以寻址1024*1024*4K=4G的物理内存。另外,在Linux的X86架构引入了3级页表机制(包括了页全局目录、页中间目录和页表)。

【参考】

1深入分析Linux内核源码

2OReilly.Understanding.the.Linux.Kernel.3rd.Edition

3、PPT: http://www.docin.com/p-54896290.html

4http://www.ibm.com/developerworks/cn/linux/l-memmod/

-----------------------------------------------------------------

zzfrom: http://chenxu.yo2.cn/articles/linux_memory.html





本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/8144188.html,如需转载请自行联系原作者

相关文章
|
3月前
|
存储 Linux 编译器
进程的虚拟地址空间
进程的虚拟地址空间
|
5月前
|
存储 Linux
虚拟地址空间
虚拟地址空间
38 0
|
9天前
|
存储 C++
进程地址空间
进程地址空间
|
3月前
|
搜索推荐 Linux
内存学习(二):物理地址空间虚拟地址空间布局
内存学习(二):物理地址空间虚拟地址空间布局
75 0
|
4月前
|
索引
虚拟地址与物理内存地址是如何映射的
虚拟地址与物理内存地址是如何映射的
|
9月前
|
存储
物理地址和逻辑地址的
最近一直在学8086!对于问题“8086 CPU 能提供20位的地址信息,可直接对1M个存储单元进行访问,而CPU内部可用来提供地址信息的寄存器都是16位,那怎样用16位寄存器来实现20位地址寻址呢"明白了不少。
55 0
|
5月前
|
存储 缓存 Linux
系统内存管理:虚拟内存、内存分段与分页、页表缓存TLB以及Linux内存管理
虚拟内存的主要作用是提供更大的地址空间,使得每个进程都可以拥有大量的虚拟内存,而不受物理内存大小的限制。此外,虚拟内存还可以提供内存保护和共享的机制,保护每个进程的内存空间不被其他进程非法访问,并允许多个进程共享同一份物理内存数据,提高了系统的资源利用率。虚拟内存的实现方式有分段和分页两种,其中分页机制更为常用和灵活。分页机制将虚拟内存划分为固定大小的页,将每个进程的虚拟地址空间映射到物理内存的页框中。为了减少页表的大小和访问时间,采用了多级页表的方式,将大的页表划分为多个小的页表,只加载需要的页表项,节约了内存空间。
187 0
系统内存管理:虚拟内存、内存分段与分页、页表缓存TLB以及Linux内存管理
|
8月前
|
存储 Linux
你真的了解虚拟内存和物理内存吗
你真的了解虚拟内存和物理内存吗
虚拟内存
虚拟内存扩展了计算机的实际内存,本期将主要讲解虚拟内存的概念与作用
|
11月前
|
存储 安全 编译器
【Linux】虚拟地址空间 --- 虚拟地址、空间布局、内存描述符、写时拷贝、页表…
【Linux】虚拟地址空间 --- 虚拟地址、空间布局、内存描述符、写时拷贝、页表…