计算机基础

看内核的时候发现很多东西都处于似懂非懂的状态,比如MMU、TLB,甚至各个寄存器的作用,今天就认真地学习一下这些东西。首先先来看CPU的寄存器:

    32位CPU中有4个数据寄存器,分别是EAXEBXECXEDX。数据寄存器用来保存操作数和运算结果,从而节省读取操作数所需占用总线和访问存储器的时间。EAX通常称为累加器,用累加器进行的操作可能需要更少的时间。可用于乘、除、输入/输出操作,使用频率很高。EBX称为基地址寄存器,可作为存储器指针来使用。ECX称为计数寄存器,在循环和字符串操作时,要用它来控制循环次数。在位移操作中,如果位移多位时用CL来指明位数。EDX称为数据寄存器,在进行乘除运算时,可以作为默认操作数参与运算,也可用于存放I/O的端口地址。这四个寄存器不仅可以传送数据、暂存数据保存算数逻辑运算结果,而且可以作为指针寄存器,所以这些32位寄存器具更具有通用性。

    有两个变址寄存器为ESIEDI,其中低16位对应先前CPU中的SIDI,对低16位的数据的存取,不影响高16位的数据。他们的主要用途用于存放存储单元在段内的偏移量,用他们可实现多种存储器操作数的寻址方式,为以后不同的地址形式访问存储单元提供方便。

    指针寄存器EIP,其低16位对应先前CPU中的BPSP,对低16位的数据进行存取不影响高16位的数据。

    2个32位通用寄存器EBPESP,主要用于访问堆栈内的存储单元,并规定:EBP为基指针,可直接存取堆栈中的数据,ESP为堆栈指针寄存器,可访问栈顶。

    段寄存器为了实现段式管理,其中包括代码段寄存器ECS、数据段寄存器EDS、附加段寄存器EESEFSEGS、堆栈段寄存器ESS

    运算结果标志位包括进位标志CF、奇偶标志位标志结果中“1”的个数、辅助进位标志AF、零标志ZF判断结果是否为0、符号标志位SF指示结果的正负号、溢出标志位OF。

    状态控制标志位用来控制CPU的操作,要通过专门的指令才能使其变化。追踪标志位TF为1时CPU进入单步执行状态。中断允许标志符IF用来决定是否响应CPU外部可屏蔽中断发出的中断请求。方向标识符DF用来决定在串操作指令执行时指针寄存器调整的方向。

    32位标志寄存器增加的标志位:I/O特权标志位IOPL,嵌套任务标志NT,重启动标志RF,虚拟8086方式标志位VM。

上面只是一些通用寄存器,下面开始看一下在看内核的时候需要知道的一些寄存器的作用:

    Intel中的CR寄存器:CR0中包含有控制处理器操作模式和状态的系统控制标志,CR1保留不用,CR2中包括导致页错误的线性地址,CR3中含有页表地址。关于CPU的运行模式就不在这儿说啦。

    在看程序或者说明的时候经常会看到MMU,那MMU是什么?MMU是Memory Management Unit的缩写,针对各种CPU,MMU是个可选的配件,负责从虚拟地址到物理地址的转换,提供硬件机制的内存访问授权。现代的多用户操作系统需要MMU才能达到每个用户进程都有自己独立的地址空间的目标,涉及到的寄存器有GDT、LDT、CR0、CR3。虚拟地址到物理地址的转换在《情景分析》上面已经讲的很清楚了。

    下面接着看TLB是什么。在CPU通过分页机制访问内存的时候并不总是根据三级的结构去找到线性地址相对应的物理地址,而是优先考虑TLB是不是有,如果有的话就不必进行这个过程了。TLB中保存的是内存页表,而L1、L2 cache则是保存对应的内存数据。在X86中有四组TLB:第一组缓存一般页表的指令页表,第二组缓存一般页表的数据页表,第三组缓存大页面指令页表,第四组缓存大页面数据页表。TLB内部存储空间被划分为相同的块,块的大小与内存的页表区里页表条目的大小相同。下面看看TLB中项的结构,每个TLB表项的长度为64位:

  1. 最高20位:VPN;
  2. 接下来的6位:PID;
  3. 接下来的6位:未使用;
  4. 接下来的20位:物理页面地址;
  5. 下一位N:如果为1表示该地址使用cache;
  6. 下一位D:如果为1表示可写;
  7. 下一位V:表示valid;
  8. 下一位G:如果为1表示不检查PID。
如何查询?匹配TLB页表项中的前半部分,使用后半部分,会产生三种不同的TLB miss异常,每一种都有各自的异常处理程序:
  1. UTLB miss:访问kuseg时,TLB中没有对应的项;
  2. TLB miss:访问kseg0,kseg1,kseg2时,TLB中没有对应的映射,或者虽然有映射但是V=0;
  3. TLB mod:写操作,有映射,但是Dirty bit = 0。
TLB的查询算法:
  1. 在用户模式下访问的地址最高位为1,产生地址错误异常;
  2. 匹配VPN,如果没有,地址最高位为1则产生TLB miss,最高位为0则产生UTLB miss;
  3. 匹配PID或者Global bit=1,如果错误则产生TLB miss,或者UTLB miss;
  4. 检查Valid bit=1,如果不是就产生TLB miss;
  5. 如果D=0,操作却在写,产生TLB mod;
  6. 如果N=1,访问内存,否则访问cache。
通过程序控制可以装载数据进入TLB寄存器,然后把这些寄存器的内容装入TLB中的某一个表项,index由index寄存器或者Random寄存器的值决定。TLB指令:
  1. mtc0:把通用的寄存器的值装入TLB寄存器;
  2. mfc0:从TLB寄存器中读取数据到通用寄存器;
  3. tlbp:在TLB中查找是否有与EntryHi寄存器匹配的,如果有则匹配项的index保存在index寄存器中,没有匹配则配置Index的最高位为1;
  4. tlbr:把Index指向的TLB表项装入EntryHi和EntryLo;
  5. tlbwi:把EntryHi和EntryLo中的值写入Index指向的TLB表项中;
  6. tlbwr:把EntryHi和EntryLo中的值写入Random指向的TLB表项中。
当TLB miss或者UTLB miss时会怎么样?OS必须重新载入TLB,然后重新开始出错的进程,异常发生时的状态:
  1. EPC寄存器:指向发生异常的指令,如果指令在分支延迟槽中则指向分支指令,基本思想:当恢复了异常中的错误,将返回用户模式,并跳转到EPC指向的地址;
  2. Cause寄存器:指明异常的原因,并保存中断状态;
  3. Status寄存器:包含机器状态的信息,重要的位:Kernel/User mode bit,Interrupt Enable bit。硬件为这些位维护一个深为3的栈,发生异常时自动移位,因此异常可以嵌套2层而不需要保存这些位;
  4. BadVaddr寄存器:保存发生访问错误的虚拟地址;
  5. Context寄存器:高11位由程序控制,接下来的19位被设为发生异常的虚拟地址的VPN,最后两位永远为0。
发生UTLB miss时:
  1. 设置EPC;
  2. 设置Cause;
  3. 设置Status,把K/U和IE移一位,并把current K/U和IE置0,即进入内核模式,中断关闭;
  4. 设置BadVaddr,保护产生异常的虚拟地址;
  5. 设置Context,高11位不变,接下来的19位设成发成错误的虚拟地址的VPN;
  6. 设置TLB EntryHi,使它包含出错地址的VPN。
    处理器的高速缓存是什么东西?CPU为了更快的执行代码,在从内存读取数据时,不只是读自己想要的那一部分,而是读取足够多的字节来填充高速缓冲行,当CPU访问相邻的数据时就不必每次都从内存中读取,提高了速度。但是这在多核的情况下就产生的数据同步的问题,这是芯片设计者定制了一个规则,当一个CPU修改高速缓存行中的字节时,计算机中的其他缓存行会被通知,他们的高速缓存将视为无效。从这些请款看来在设计数据结构的时候,应该尽可能把只读的数据和可读写的数据分开,并且尽量将同一时间访问的数据组合在一起,这样CPU能一次将需要的数据读入。
-------------------------
个人理解,欢迎拍砖。
posted @ 2011-08-13 20:25  GG大婶  阅读(1438)  评论(0编辑  收藏  举报