逻辑上,内存是一个有序字节组成的数组,每个字节有唯一的内存地址,那这个地址到底是啥。
cpu通过数据,地址,控制总线完成与内存的交互。地址总线一共有32根,每一根的值是1或0。内存最基本的单位是字节,8个二进制。
内存地址是对每一个字节的映射。换句话说,是32位二进制数相对一个8位二进制数的映射。(数组是什么,是一个整数对某一个数组元素的映射)
内存地址是地址总线上所有位构成的一个值。用这个值可以操纵内存中唯一的一个字节。
如何快速有效的对字节寻址呢?最早最通用的cpu(80x86)中应用了一种称为段的寻址技术(现在仍然使用),就是对所有的字节分段访问。
在采用分段技术之前,cpu是直接面向内存访问,cpu的针脚上的值就是地址的值。分段后,cpu面向的是段地址和段内偏移地址(针脚上的值不再是直接的内存地址了),之后由某一个部件根据cpu给出的段地址和段内偏移地址换算出真正的内存地址。
既然本来就可以访问到内存,由何必费那么大劲搞一个分段的寻址方式呢? 跑一下题,描述一下分段技术应用的上下文。分段的出现在操作系统中,没有分段就没有操作系统。在此之前,还没有一个现代意义上的操作系统(之前都是批处理作业,不对内存划分空间)。再然后就能有汇编语言,有编译器,有高级程序语言,有更好看的窗口桌面,能有更好玩的游戏...
分段提供了最基础的对内存的保护能力。如果不分段,没有任何方式不让一条指令访问某一个内存区域(程序员写的指令能读写任意一个内存地址内容,想想这样的后果)。那分段机制如何保护内存呢。
在80x86中,段地址又叫段选择符,共16位,存放在CS、DS、ES、SS、FS、GS寄存器中,其中起作用的有14位。段偏移地址有32位。在操作系统层面,保存着一张大表(段描述符表,也叫GDT表,存在内存,在操作系统初始化时创建),这个表的的索引就是段地址,或者段选择符(终于知道为什么会叫选择了)。程序中的某条指令给出一个逻辑地址(就是段地址和段内偏移地址),通过段地址查GDT表,就能知道这个段是干啥的,这个段多大,这个段从哪开始,从哪结束,更重要的是它的访问权限,操作系统会比对正在运行程序指令的状态权限,来决定这条指令能不能访问该地址。通过段地址查GDT表,知道段的首地址,再加上段内偏移量,就可以得出物理内存地址了。
图片来自杨炯老师的《linux内核完全剖析》第五版
pdf下载地址:http://oldlinux.org/download/CLK-5.0-WithCover.pdf
原文地址:https://www.cnblogs.com/gengqzh/p/10500189.html
时间: 2024-10-18 06:23:37