[OS_0x01]实模式 --> 保护模式(段式-->段页式)

``本文的一些截图来自于<IntelDEV卷3>和<x86汇编从实模式到保护模式>`

最近复习一些操作系统的知识,首先遇到了个坑便是计算机寻址问题.
本文是一些偏理论的东西(汇编可能在工作中用不到,需要的时候再深入研究吧- -!)

本文参考的一些博客和书本:

<a href=http://blog.csdn.net/trochiluses/article/details/8954527>[实模式与保护模式解惑之(一)——二者的起源与区别]</a>
汇编相关-从汇编研究局部变量机制
我看保护模式
x86汇编语言:从实模式到保护模式

实模式

  • 是什么

INTEL 8086CPU的寻址方式.

具体利用分段机制访问内存,访问时给出一个段基地址和一个段内偏移;(如DS:AX,其中DS和AX在这里的字长为16),访问的地址为实实在在的物理地址.

  • 为什么

    一个原因是8086特点 - 数据总线16位(字长为16)、地址总线却有20位(准确地说是CPU的寻址能力需要被设计成20位).

    这样程序员在没有特殊机制的引入时,只能访存2^16 B = 64 KB的空间(16位字长),达不到产品经理的需求(20位地址空间 = 2^20 B = 1 MB

    于是,这里设计成了使用段基地址 + 段内偏移的方式: 物理地址 = 段基地址<<16 + 段内偏移
    有个小问题就是这种方式实际上可访问的空间大于1M,即最大可以访问到0xFFFF*16 + 0xFFFF = 0x10FFEF > 0xFFFFF,多出的这些地址将从0开始(即对1M取模).

  • 实模式的段的特点 -

    • 每个段基地址都是16的倍数;

    • 每个段的最小长度是16 Bytes,最大是64 KB;<----------更新: 段的大小从1B到64KB都可以.见wiki:

      1. WIKIPEDIA.png

    • 访问的每个地址都是实际的物理地址.

  • 遗留的问题

系统程序与用户程序访问的地址共存于同一地址空间,并且一视同仁:

  • 没有权限保护(用户可以随意访问1M的全部内存地址空间)
  • 不支持多任务.

保护模式

保护模式之所以叫“保护模式”,因为他对多任务提供了保护,并加入了权限.
玛德我想起来了大二汇编时保护模式这一章跳过了因为期末不考沃日.

  • 是什么
    80386及后续系列CPU所资磁的内存寻址方式.

  • 为什么
    引入保护模式的目的有:

    • 保护 - 权限管理
    • 多任务隔离
    • 向下兼容 - ...
  • 怎么做
    这里简要介绍一下保护模式.

    • 寻址方式的改变:

    • 实模式下 - 可以直接访问段基地址(段寄存器16_bit)<<16 + 段内偏移并做一些单字长操作(访存/赋值) .

    • 保护模式下 -
      先来点废话:
      由于需要引入权限管理, 需要:访存时指出当前执行指令的人有没有权限访问这个地址;
      这句话至少包括了2点:

      • 当前指令的权限描述;
      • 目标地址的权限描述.

      所以当前的解决方案已经呼之欲出了:需要一个数据结构来描述内存地址.

保护模式下的寻址_part1段式(1MB --> 4GB 32Bit)

  • 机器启动流程 - 一个PC启动时都会先进入实模式,接着由某指令转入保护模式.

  • 段描述符表 - 是一堆段描述符的集合,有GDT和LDT.其中GDT是全局描述符表Global Descriptor Table,该表是为整个OS服务的,在进入保护模式之前定义好(由bootloader). LDT,相对应地,则是局部段描述表,是每个进程自己独有的?.

    GDTR寄存器存放着GDT的地址.
    理论上说GDT可以位于4GB中的任何一个位置,但因为需要从实模式转保护模式,所以一般只在1M以内的位置...(参见<x86从实模式到保护模式>)

    2. GDTR,48bit的寄存器

  • 描述符表项 - 无论是全局还是局部的描述符表,表项字段都如下图所示:(it‘s a fucking Data Structure!)

    3. 描述符表项

    里面记录了这个段的:

    • 段基地址BASE(32位一共,被分割成了3部分)
    • 段界限LIMIT(20位)
    • 段界限Granularity (Seg.LIMIT字段)的单位(0 - 1B/1 - 4KB).

段界限及其单位表示 段内偏移的最值(对于向上增长的段而言表示了最大值,而向下增长的段如堆栈段则是表示段内偏移的最小值哦)<------why?举个例子如下:(如有错误请指出)

0xFFFFFFFF |********|
                     ... 
0x00A01001 |********|<-----SS:EBP (指向栈底) }
0x00A00FFF |********|<-----SS:ESP (指向栈顶) }EBP,ESP两个的值可能都是段内偏移
                     ...
0x00A00002 |        |
0x00A00000 |********|<-----SS:<段界限*粒度+1> Suppose a MIN_VAL's linear addr
                     ...
                     |
0x0000FF00 |********|
                     ...
0x00000002 |        |(每次存进来一个字2 bytes,所以地址上相差2)
0x00000000 |********|<-----SS:0
0.假设某程序运行时调用了一个函数,这时该程序的动作包括`保存现场`,`声明堆栈段`;我们关心的是声明堆栈段(用来存储函数参数、局部变量等).
1.这个段也有基址(我们假设为0x0,后面你就知道其实这个假设是ok的)
2.声明时要做的事是指定EBP、ESP(有点钦定的感觉),接着ESP减2,push进来函数参数之类的,每次push,ESP会自动减2(别问我为什么自动),每次pop,ESP会自动加2
3.上面所说的段内偏移的最小值,指的就是当ESP一直减,最多只能减到<段界限*粒度> ,再减就提示堆栈溢出了.

<a href=http://www.360doc.com/content/16/0223/12/28062682_536641957.shtml>汇编相关-从汇编研究局部变量机制</a>

所以现在一个段最大可以是4G,最小可以是1B.

理论上访问4G内存不再需要什么段啥的,一个段足矣(这种情况便是所谓的平坦模式):


4. flat mode
  • 段选择子 - 段寄存器CS/DS/SS/etc...此时不再是被用来左移并相加的对象,而是存放一个索引+标记+权限,这个索引指向了需要访问的段所在描述符.这些存放的内容被称为段选择子.

    5. 段选择子

    由段选择子的索引量可以看出一个表最多有2^13=8192个表项
    (实际上32位处理器如80386,他们的段寄存器的长度为32位,只不过后面16位我们不可见,是处理器用作描述符高速缓存的)

  • 整体描述 (from high level)


    6. 线性地址如何得到-此图来自<a href=http://bbs.chinaunix.net/thread-2083672-1-1.html>thread</a>('8'是表示立即数填充Index字段)
  • 权限 :
    权限字 0 - 3(高 - 低),如下:


    7. 特权级别
  • 权限的判断机制:

    • 代码段CS寄存器里的CPL为当前执行权限,称其为CPL(current);
    • 数据段DS(或SS等,发出寻址请求指令所在寄存器)里的CPL为请求权限,称其为RPL(request);
    • 段描述符中的段权限DPL;

3者进行一个判断,如果合法(比较复杂的判断,例如满足DPL>=CPL,DPL >= RPL,且CPL <= RPL等),则进行地址转换(此时得出的是虚拟地址,需要转为物理地址,转换又跟此时的另一些东西相关,见part2),转换后最终寻址到所需地址.

总之,在保护模式下做什么事都得先进行权限检查.

PS: 这里的ring 0也就是所谓的内核态,而linux中的用户态是ring 3.

参考:<a href=http://blog.csdn.net/xiao_0429/article/details/47165169>我看保护模式</a>
(具体如何做的不深入了,涉及太多汇编相关的东西,知道就好)<-------fuck that!既然有兴趣读到这些知识,最好搞懂, 不然辜负这些知识.

保护模式下的寻址_part2段页式(更复杂的机制来了)

  • 整理一下目前为止接触到的东西:
    1. 机器启动阶段先进入的是实模式(1M内存寻址空间,20Bit地址 + 16Bit数据), 然后由某指令转入保护模式.
    2. 保护模式_段式 - 最主要是为了解决权限问题,比如数据段不能被拿来当代码段运行,当前权限低的不能访问权限高的段等.
      2.1 保护模式_段式 - GDT 和LDT(本来该设计是整个OS有一个GDT,每个进程有自己的LDT,而linux的进程极少使用LDT,基本上GDT和LDT起始为止都是0x00000000
      2.2 GDT的地址和长度存放于GDTR(Global Descriptor Table Register),其中0~15为GDT长度,16~47为GDT所在地址.
  1. 保护模式_段式 - the entry of GDT(or LDT),每个表项描述了一个段.
  2. 段选择子 - 段寄存器(如CS,SS等)存放的内容包括INDEX、TI、RPL.
  3. 权限4个等级(特权0 - 内核态, 特权3 - 用户态)- also known as ring 0 ~ 3.不管做什么都需要进行权限判断。
  • 目前为止,访问内存是这样访问的:
用户提供段选择子(Index,TI,RPL)和段内偏移(offset)  |
GDTR/LDTR提供了GDT和LDT的地址和长度                |-->权限检查(结合代码段CS中的权限字,段选择子中的权限字和GDT/LDT表项中的权限字DPL进行检查)
                                                        -->找到Index所在段,取出其段基地址
                                                            -->把用户提供的段内偏移与段基地址结合构成一个完整的地址(这里称为**线性地址**)

也就是上面的图6表示的.
在单纯只有分段的情形下,这个线性地址就是物理地址.

  • 目前为止,基于段的内存替换是这样进行的:
  • 分段的缺点 - 内存外部碎片.(段大小不确定,使用一段时间之后,内存可能会有很多微小的空洞,不足以提供分配)===>因此分页机制就来了.

分页机制

  • 大致描述:
    • 4GB物理内存以4KB大小分为 4GB / 4KB = 1048576(1M)个页,页也称为页框(page frame).
    • 引入虚拟内存的概念.对于每个进程而言,大家都有自己的4GB内存空间,并且通过一定的手段(后面解释), 按页为单位映射到实际的物理内存上.
    • 映射表,上一点提到的虚拟内存中的页面与实际内存物理页面间通过映射表来联系,甚至每个进程都有自己的映射表, 另外这个映射表也很可能是分级的以解决空间利用效率.
    • 页面的管理和页面的分配没有关系,线性地址(也就是段管理单元得到的地址)也与页面的分配没有关系.
8. 段--线性地址---页映射表(简称页表)---物理页
  • 详细深入:
  • MMU(Memory Management Unit)是CPU中的内存管理单元.
  • 页目录:分页机制实际上更复杂一些,上面说的"页表"一共有1M个,每个表项有4Bytes,那么整个表有4MB这么大. 每个进程有自己的页表,并且一般不会用到这么大,每次换入换出RAM是不是TM很烦?页目录就是解决这个的.(也就是上文里提到的页映射表分级问题)
  • 4GB内存中一共有1M个页 --> 现在把这1M分成2个层次,即 1K * 1K,给第一个1K一个新的名字——页目录表(Page Dir. Tbl.),第二个1K是真正的页表. 页表的规模变小了但相应地数目变为1K个,所谓页目录表,就是存放这1K个页表的页.这里需要注意两种表的表项大小都是4B,所以两种表的大小正好都是4K即一个页的大小.
    还是有点乱,见下面一系列的图.(退后 我要开始装逼了!)
    Powered By Processon.com
  • Naive的页表:


    Naive页表
  • 分层次的页表:


    分层次的页表
  • 分段/分页的关系:


    分段/分页的关系
  • 段页式物理地址的获取:


    段页式物理地址的获取

一些其他问题:

  • 吐槽 - 为什么经常弄不懂呢?一部分原因是自己太懒,另一部分书确实也有些没讲清楚或者考试不考尼玛就跳过了.(归根到底还是自己的问题,别怪别人...)


    9.-1 教科书中出现的地址转换还是不够精确,没有说明段选择子也没有设计页的分层
  • 目前关注的这些应该还算是寻址方式的一些东西,而上面有提到需要给进程分配页面,以及在该页面不怎么使用时换出,那么这些动作是怎么做的呢?
    9. 有错请指出,该图来自<a href = http://www.cnblogs.com/bizhu/archive/2012/10/09/2717303.html>cnblog</a>

上面最后几个图如果看不清请猛戳<a href = https://www.processon.com/view/link/578a274ce4b0701cc02852c6> 我的文件</a>
欢迎大家纠错,共同进步.


写这篇的时候联想到的一些问题:(亟待深入)

  • 快表? - ok.

  • 缺页中断 ?

  • dirty ?

  • 伙伴系统 ?

  • slab/slub ?

  • malloc ?

  • page cache / buffer cache 又是什么呢 ?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • 本文试图用有限的篇幅来阐述80386保护模式重要知识点。本文不是一个系统全面的知识介绍,您可能需要了解相关的803...
    JeffreyLi阅读 2,089评论 0 10
  • 最近开始想稍微深入一点地学习Linux内核,主要参考内容是《深入理解Linux内核》和《深入理解Linux内核架构...
    ice_camel阅读 1,765评论 0 2
  • 1 内存寻址 1.1 物理地址、虚拟地址以及线性地址 物理地址: 物理内存的内存单元地址 虚拟地址: 程序员看到的...
    疯狂小王子阅读 2,781评论 3 21
  • 但是我早早的起来了却在玩手机。持续性一事无成。这不是搬起石头砸自己脚吗? 解决拖延症的方法最好就是硬刚 在学习上一...
    Charging99阅读 124评论 0 0
  • 照片加上水中倒影之后,感觉整个世界都不一样了。
    小辑轻渡阅读 308评论 0 0