计算机组成与结构概述.doc
如有侵权,请联系网站删除,仅供学习与交流计算机组成与结构概述【精品文档】第 15 页计算机的基本概念快速的向用户返回计算结果是编写一个成功的软件中的关键部分.操作系统是用户程序和硬件的接口,它提供许多服务和管理功能.其中,最重要的功能有:1)处理基本输入输出操作;2)分配存储空间和内存;3)为多个程序同时使用计算机提供支持.系统软件提供公共服务,包括操作系统,编译器,汇编器;编译器:将高级语言语句翻译成汇编语言语句的程序.任何计算机的底层硬件都执行着同样的基本功能:输入数据,输出数据,处理数据和存储数据.计算机的五个经典组成部分是输入,输出,存储器,数据通路以及控制器,后两个我们有时合称为处理器.有些设备即向计算机提供输入也接受输出,例如:网络和硬盘.光电式鼠标取代机电式鼠标再次例证了一个普遍现象:电子设备成本的下降和可靠性的提高促使电子方案取代旧的机电方案.动态随机存储器(DRAM):集成电路式存储器,可以随机访问任何单元;高速缓存(cache:一块小容量高速存储器,作为大容量存储器的缓冲区.高速缓存使用了不同的内存技术静态随机存储器(SRAM).SRAM更快但集成度低,因此也就比DRAM更贵些.内存(memory):正在运行着的程序以及其所需的数据所驻留的存储介质;易失性存储器:持续供电才能保存数据的存储设备,如DRAM.内存是易失性存储器.摩尔定律:晶体管容量没1824个月就会翻一倍.硬件设计中的四个基本准则:1)简单源自规整;2)越少越快;3)加快执行常用操作;4)好的设计需要合适的折衷.当前的计算机构造基于两个关键性原则:1)指令以数据形式表示;2)和数据一样,程序存储在存储器中,并且可以读写.CPU与指令集(Instruction Set)1. 什么是CPU ?电脑的核心!CPU (Central Process Unit)中央处理器2. CPU的主要工作是什么?执行一串指令.3. 指令:CPU能执行的最基本的操作单元譬如说:两个整数相加、相减4. 不同的CPU=>指令集不同。5. 某个特定CPU所实现的指令集称为指令集结构Instruction Set Architecture (ISA).a) 例: Intel 80x86 (Pentium 4), IBM/Motorola PowerPC (Macintosh), ARM, Intel IA64RISC思想(精减指令集)指令集更小,更简单, 从而能有效构建更快硬件.由软件通过组合简单运算来完成复杂运算.为什么MIPS,而不是 Intel的X86?1.MIPS简单,漂亮。不希望大家被一些细节所困扰(只见树木,不见森林);2.MIPS广泛应用于嵌入式系统,x86很少应用嵌入式系统, 而嵌入式计算机比PCs机多很多;3.中国芯?龙芯I代, II代(95%MIPS),获得MIPS授权.*寄存器registers与高级语言不同(如C或Java), 汇编语言不能使用变量为什么呢? 让硬件简单一些汇编语言的操作数是寄存器registers寄存器位于计算机硬件的某个特殊位置,数量有限操作只能在寄存器上进行!MIPS寄存器数量:32个为什么? 越小(少?)越快Smaller is faster优点: 由于寄存器在硬件中, 其访问速度非常快(10亿分之一秒1 billionth of a second)缺点: 由于寄存器在硬件中, 其数量有上限32个变量多于32个怎么办?放在核心硬件外面,用的时候拿进来效率问题如果不是太多:仔细编写代码来高效使用寄存器A=3 B=4 C=A+B D=A-B E=C*D F=C/D 使用6个A=3 B=4 C=A+B D=A-B A=C*D B=C/D 使用4个A=3 B=4 C=A+B A=C-B A=C-B B=C/A A=C/A 使用3个每个MIPS寄存器是 32位宽在MIPS中我们将32位组织在一起,称为字word寄存器编号:0 到 31每个寄存器可通过编号和名字来指定通过编号指定:$0, $1, $2, $30, $31C语言(其他大多数高级语言也一样)中,变量首先要声明并给定一个类型例如: int fahr, celsius; char a, b, c, d, e;每个变量只能表示其所声明的类型的值 (不能混用及比较int型和char型变量).在汇编语言中, 寄存器没有类型; 运算(符)决定如何处理寄存器,即运算(符)确定寄存器内容的数据类型.*例1: a = b + c + d - e;(注意理解)add $t0, $s1, $s2 # temp = b + cadd $t0, $t0, $s3 # temp = temp + dsub $s0, $t0, $s4 # a = temp-e例2: f = (g + h) - (i + j);add $t0,$s1,$s2# temp = g + hadd $t1,$s3,$s4# temp = i + jsub $s0,$t0,$t1# f=(g+h)-(i+j)MIPS汇编语言中:寄存器=变量一行一条指令 (简单操作)C 变量: $s0 - $s7,对应寄存器1623;临时变量(temporary): $t0 - $t7,对应寄存器815;Zero: $zero立即数:数值常数代码中经常出现,因此有专门的指令.加立即数指令(Add Immediate):addi $s0,$s1,10 (in MIPS)f = g + 10 (in C)这里MIPS寄存器 $s0,$s1对应于C变量f,g 语法和add指令类似区别:最后一个参数是数,而不是寄存器 register*没有减立即数C变量映射到寄存器,但寄存器有限超过32个元素的数组怎么办?一般把这种数据结构放在内存memory中MIPS算术指令仅能对寄存器操作,不能直接操作内存.数据传送指令 在寄存器和内存之间传送数据:内存到寄存器;寄存器到内存*指定内存地址:寄存器:包含指向内存的指针数值偏移量offset (以字节为单位)内存地址为这两个值的和*例:8($t0)内存地址为:$t0的值+8(字节)Load 指令语法(Instruction Syntax):1 2,3(4) 1是指令名字(operation name)2是接收值的寄存器(register that will receive value)3数值偏移量(单位:字节)numerical offset in bytes4包含指向内存指针的寄存器(register containing pointer to memory)MIPS 指令名字(Instruction Name):lw (意即Load Word, 故每次装入32位即一个字) 例:lw $t0,12($s0)该指令取出$s0中的指针, 加上12, 然后从计算的和所指的位置的内存中取得值,放到$t0中.$s0 称为 基寄存器base register12 称为 偏移offset偏移通常用于访问结构体或数组的元素: 基寄存器指向结构体或数组的起始位置(注意偏移量必须是常数 (即在编译时已知).*sw (即Store Word, 每次存储32位或一个字)例:sw $t0,12($s0)该指令将$s0中的指针加上12,得到内存地址,然后把寄存器$t0中的值存储到该内存地址中*lw和sw一个是取出,一个是存储,注意区分重要概念: 寄存器可以保存任意32-位数值. 该值可以是 对于 add $t2,$t1,$t0$t0和$t1中一般为数值而对于lw $t2,0($t0) $t0中一般为指针不要混用!内存中的每个字都有地址, 这和数组中的下标类似早年的计算机对内存的编号方法类似于 C 对数组的编号:Memory0, Memory1, Memory2, 计算机既要访问 8-位 字节 也要访问字 (4 bytes/word)现代计算机按字节编址, (即,“字节寻址”) 因此相临两个32-位(4 byte)字的地址差别为 4. Memory0, Memory4, Memory8, *lw 如何确定C变量A5的偏移量?A5 4x5=20 : byte v. word 手工编译以下语句:g = h + A5; g: $s1, h: $s2, $s3: A 的基地址首先将数据从内存传到寄存器:lw$t0,20($s3) # $t0 gets A5将20与$s3相加来选定择A5, 放到 $t0中然后将结果和h相加,并放到g中add $s1,$s2,$t0 # $s1 = h+A5*缺陷:经常会忘记,对于计算机的操作单位“字”序列,但在机器编址是字节。故两个相临的字之间地址不是差一个。很多汇编程序员常犯的错误是,取下一个地址时,简单加1。另外, 谨记对于 lw 和 sw, 基址和偏移量之和必须是4的倍数 (即需要 字对齐alignment)注:Aligned:对齐的.法则:寄存器 PK 内存如果变量数比寄存器个数还多,怎么办?1.编译器试图把最常用的变量放到寄存器中2.不是很常用的变量放到内存中: spilling为什么不把所有变量都放到内存中呢?1.Smaller is faster:寄存器比内存快2.寄存器能力更强: MIPS一个算术指令就可以完成,读两个数,进行运算,并写结果MIPS一个数据传送指令只能读或写一个操作数,而无运算C (MIPS也一样) 提供了语句标号Labels 来支持 “goto” 跳转到代码所在处.小结: 1.内存可访问到字节byte, 但lw,sw每次访问一个字.2.lw和sw所使用的指针就是内存地址, 可以通过使用偏移量offset来进行增减.3.分支让我们能在运行时( run-time )做决定,而不是在编译时(compile-time)进行.4.MIPS决策的条件语句有: beq(=) and bne(!=).溢出: 由于计算机精度的限制,而导致的算术运算错误.add (add), 检测溢出add unsigned (addu), 不检测溢出左移Shift Left: sll $s1,$s2,2 #s1=s2<<2将$s2的值左移2位,结果放到$s1中,在右边添0; C语言的 <<*左移(sll),右移(srl).jal 存储返回地址到寄存器中($ra),注:$ra的寄存器号为31.jr $ra 跳回该地址处MIPS指令小结 语义1.逻辑运算:1)与 and $s1,$s2,$s3 $s1=$s2&$s3 2)或 or $s1,$s2,$s3 $s1=$s2|$s3 3)或非nor $s1,$s2,$s3 $s1=($s2|$s3) 4)立即数与andi $s1,$s2,100 $s1=$s2&100 5)立即数或ori $s1,$s2,100 $s1=$s2|100 6)逻辑左移sll $s1,$s2,10 $s1=$s2<<10 (来做2的幂的乘法) 7)逻辑右移srl $s1,$s2,10 $s1=$s2>>10 8) sra (算术右移): 右移空出来的位进行符号扩展, 来做2的幂的除法.2.条件转移: 1)相等转移 beq $s1,$s2,L 如果$s1等于$s2,跳转L处 2)不等转移 bne $s1,$s2,L 如果$s1不等于$s2,跳转L处 3)小于比较 slt $s1,$s2,$s3 如果$s2小于$s3,$s1=1;否则$s1=0; 4)小于比较 slti $s1,$s2,100 如果$s2小于100,$1=1;否则$s1=0立即数3.无条件跳转: 1)跳转 j L 跳转到地址L(转移到目标地址0 2)寄存器跳转 jr $ra 跳转到$ra (用于过程返回) 3)跳转并链接 jal L $ra=PC+4;跳至L(用于过程调用)4.其他: 1)立即数高位取: lui 2)传送:move 3)乘:mult 4)立即数乘:multi 5)立即数取:li 6)小于则分支:blt 7)小于等于则分支:ble 8)大于则分支:bgt 9)大于等于则分支:bge *上述中除了(1)中的立即数取高位,其他的都是伪MIPS指令; 伪指令:不能直接转成机器语言,而是要先转成其它MIPS指令的MIPS指令; 解析伪指令时,汇编器需要使用附加寄存器.1.任何数与0“与”产生 0 ,与1“与”不变. 这可以用来产生掩码mask.2.类似的注意到,任何数与1“或”,结果为1,而与0做“或”运算,结果为原数.这可以用于强制字串的某些位为1.寄存器约定: 1.$0不可改变,始终为0;$s0-$s7和$sp如果改变必须恢复, 所有存储寄存器以S开头.2. $ra,$v0-$v1,$a0-$a3,$t0-$t9是临时寄存器,可以改变,且不需要恢复.谨记: Caller/callee 仅需要保存其要使用的临时/存储寄存器,而不是所有的寄存器.由于所有的指令和数据都存储在内存中,所有的东西都有内存地址:指令, 数据指令集随时间的演化,产生“向后兼容”指令格式:I型:用于有立即数的指令, lw和sw (偏移量也可看成立即数), 分支语句(beq和 bne), (但不用于移位指令;)J型: 用于j和jal R型: 用于所有其他的指令R格式指令每个“字段”的位数为: 6 + 5 + 5 + 5 + 5 + 6 = 32为了好记,每个字段名字如下:在这个幻灯片和书中, 每个字段看成5位或者6位无符号数, 而不是作为32位整数的一部分.每个寄存器字段正好是5位, 故可以指定0-31间的任意正整数. 每个这样的字段可以指定 32个寄存器中的一个.Opcode,即op,指令的基本操作,通常称为操作码, 对所有R格式指令,此数为0.rs:第一个源操作寄存器;rt: 第一个源操作寄存器;rd:存放操作结果的目的操作数寄存器;shamt:位移量,除了移位指令外,该字段设置为0.funct:函数, 和opcode一起, 共同指定指令的确切含义注:reg表示031之间的一个寄存器号I格式指令(用于有立即数的指令)定义如下的位数的 “字段” : 6 + 5 + 5 + 16 = 32 bitsopcode: 与前面的相同,只是由于没有funct字段, opcode独立指定指令的I格式rs: 指定寄存器操作数 (如果有的话)rt: 指定保存计算结果的寄存器(这也是为什么称为目标寄存器 “rt”的原因),或者对于一些指令指定其他操作数.opcode 指定beq和bners和rt指定要比较的寄存器立即数指定什么呢?立即数Immediate仅有16位PC (Program Counter) 存有当前要执行指令的字节地址;指向内存的32位指针因此immediate无法指定整个跳转的地址J格式指令对于分支, 可以假定跳转到不太远的地上, 因此可以指定PC的变化.对于一般的跳转 (j和jal), 我们可能需要跳转到内存中的任意地址.理想的情况, 指定跳转到32位内存地址处.不幸的是, 无法把6位opcode和32位地址,一起放到单个32位字中, 因此需要妥协.保持Opcode字段与R格式和I格式兼容.把其它所有字段合成为一个,形成一个大的目标地址空间.和前面分支跳转一样,将只跳转到字对齐的地址, 因此最后两位总是00 (二进制).因此,可以默认最后二位为00,而不必专门指定.分支使用PC相对寻址, 跳转使用绝对寻址.反汇编很简单,首先需要解码opcode字段. (后面会讲)IEEE 754 浮点数标准 是被广泛接受的用于表示浮点数的标准 (自1997 年以来的桌面计算机和工作站都遵循此标准)浮点数使我们能够:表示既包含整数部分,又包含小数部分的数; 能高效的使用位数.存储非常大和非常小的数的近似值.在浮点数中,除0应该得到 ± , 而非溢出.浮点数相加不满足结合律!注意exponent中关键在于127和指数的加减.可以根据上表中op项的值来进行反编译.反汇编的一个实例:lui的功能MAL (MIPS Assembly Language): 程序员编写代码所用的指令集; 包括 伪指令TAL (True Assembly Language): 可以转换成单个机器语言指令(32位位串)的指令集程序必须先从MAL转换成TAL,然后再转成 1和0串.当效率不是关键所在时, 我们会对高级语言进行解释,而如果要提高效率则会翻译成一种低级语言.解释器: 直接执行源(高级)语言编写的程序翻译器: 将源(高级)语言编写的程序转换成另一种(低级)语言编写的等价的程序解释器提供了指令集独立性:可以在任何机器上运行;翻译/编译后的代码通常更高效,因此有更好的性能;翻译/编译有助于 “隐藏” 程序的 “源码”执行程序的步骤 (翻译):编译器: 输入: 高级语言代码(如C,Java如foo.c)输出: 汇编语言代码(如, foo.s for MIPS)注: 输出可能 包含伪指令伪指令: 汇编器能理解,但机器不能理解的指令.需要讨论四类地址:PC相对寻址 (beq, bne): 不重定位绝对地址 (j, jal): 总要重定位外部引用 (通常用jal): 总是重定位数据引用 (通常使用 lui和ori): 总重定位现实中, 装入器即是操作系统 (OS) 装入是操作系统的任务之一同步数字系统: 处理器硬件, 如MIPS, 就是一种同步数字系统的实例同步数字系统由两种基本电路组成:组合逻辑电路;状态单元.ISA是非常重要的抽象层:硬件与软件的协议.电压是模拟量analog, 量化为 0/1逻辑门布尔代数的重要意义在于: 由AND, OR 和 NOT 构建的门电路和布尔代数的代数式间存在一一对应+ 即 OR, 即 AND, x 即 NOT,例:算术逻辑单元(ALU)数据多路复用器 (这里2选1, n位宽):例: N 个1位位宽mux(连接法!)MIPS有多种指令: 公共的步骤是什么?1.Stage 1: 取指无论何种指令, 首先必须把32-位指令字从内存中取出。(可能涉及缓存结构)在这一步,我们还需要增加PC (即PC = PC + 4, 以指向下一条指令,由于是按字节寻址,故+4);2. Stage 2: 指令译码Instruction Decode在取到指令后, 下一步从各域(fields)中得到数据(对必要的指令数据进行解码)首先,读出Opcode,以决定指令类型及字段长度接下来,从相关部分读出数据对add, 读两个寄存器对addi, 读一个寄存器对jal, 不用读寄存器3. Stage 3: ALU (Arithmetic-Logic Unit)大多数指令的实际工作在此部完成: 算术指令 (+, -, *, /), 移位, 逻辑 (&, |), 比较 (slt)装入loads和存储stores呢?lw $t0, 40($t1)要访问的内存地址 = $t1的值 + 40因此,在这一步需要做这个加法运算4. Stage 4:内存访问Memory Access事实上只有load和store指令在此stage会做事; 其它指令在此阶段空闲idle或者直接跳过本阶段由于load和store需要此步,因此需要一个专门的阶段 stage来处理他们由于cache系统的作用,该阶段有望加速如果没有caches,本阶段stage会很慢;5.Stage 5: 写寄存器Register Write大多数指令会将计算结果写到寄存器例如: 算术, 逻辑, 移位, 装入, slt而对存储, 分支, 跳转呢?结束时,不写内容到寄存器这些指令在第5阶段空闲,或者干脆跳过例:是否能有不同的步骤? 是!其他计算机结构可能会不同前述指令至少在某一步空闲(idle),为什么MIPS还要有步?五步能使所有的操作有统一的步骤.还有一个指令五个阶段都需要(即无空闲): load通用寄存器用于第二步 (Read) 和第五步(Write)MIPS共有32个通用寄存器内存用于第一步 (Fetch) 和第 4 步(R/W)Cache系统使得这两步和其他步骤同样快(平均而言)其他寄存器为了实现每个时钟周期执行一步, 在各步(stage)之间插入寄存器以保存阶段变换过程中的中间数据和控制信号.注: 寄存器是通用名词,意即保存位的实体. 不是所有寄存器都在“寄存器文件”中.单周期CPU: 指令的所有阶段在一个长的时钟周期中完成. 时钟周期足够长,以便能在一个周期内完成所有指令的五步,而不必中断.多时钟周期CPU: 每个时钟周期,执行一个stage指令. 时钟和最慢的stage一样长.和单时钟执行相比,有几个好处: 某个指令未用的阶段stages可以跳过,指令可以进入流水线pipelined (重叠).分析指令集结构 (ISA) -> 数据通道需求每个指令的含义由寄存器变换给定数据通道必须包含用于ISA 寄存器的存储单元数据通道必须支持每个寄存器的变换寄存器变换语言(RTL)对所有指令的共同RTL操作如下:(a) 在开始执行指令前,使用程序记数器 (PC)取址, (b) 在指令执行结束时,更新程序记数器.数据通道所需要的最后一个存储单元是理想内存,在该处存储数据和指令.执行load 指令的时间是以下几项之和:(a) PC反转;(b) 指令内存访问 ;(c) 读寄存器 ;(d) 算术逻辑单元计算数据内存地址;(e) 读内存;(f) 寄存器文件的启动时间和时钟误差 流水线延时Latency: 完整的执行一个指定任务所需要的时间;吞吐量Throughput: 在一段时间内能做的工作总量;流水线不减少单个任务的延时量,但可以减少整个任务的吞吐量;多任务同时进行,使用不同的资源;每个指令必须运行同样的步骤,在流水线中也称为阶段 “stages”, 尽管其中一些有时会“休息”idle*寄存器, 右半边红色读, 左半红色写流水线的限制: 困境(Hazards) 使下一条指令无法在所设计的时钟周期中执行。结构困境Structural hazards: 硬件不支持一些指令组合 (一个人同时叠衣服和放到衣柜中)控制困境Control hazards: 流水线结构中,对于分支语句,必须等到分支的结果后,才知道下条语句该执行什么。数据困境Data hazards: 指令依赖于前面指令的结果,而前面的指令还在流水线中 (missing sock)可以在一时钟周期中读写两次寄存器,但不可以同时读内存.流水线优化每个时钟周期仅执行指令的一部分.每个时钟周期都有一个指令完成.平均而言,执行更快.流水线面临的挑战是“困境”hazards前馈:能解决许多数据“困境”Delayed branch:可以解决控制“困境”Load 延时槽 / 互琐是必要的进一步提高性能: 超标量(superscalar)乱序执行(Out-of-order execution)由于处理器和内存间的速度不匹配,我们加入了一个新的层: 内存的缓存(Cache)Cache是主存的子集的一个拷贝.大多数处理器都含有分离的指令和数据caches.缓存中包含内存中最近使用的数据的一个拷贝.内存中包含磁盘中最近使用数据的一个拷贝Cache的工作原理: 时空局部性;时间局部性: 现在使用的数据,可能一会还要用.空间局部性: 使用内存的某一段,很可能一会儿要使用该数据附近的数据。在直接映射cache中, 每个内存地址只可能与中的某个块block关联因此, 如果内存中的数据在Cache中,只用查找 cache中的某个特定位置即可块Block是cache与内存间传送数据的单位Index: 指定cache块号 (所需要的cache行)Offset: 找到正确的块后,指定所需块中的哪个字节 即哪一列Tag: 决定除offset和index之外的字节; 用于区分所有映射到同一cache的不同内存由于多个内存地址映射到同一cache 索引, 如何知道哪个内存的内容在Cache中呢?如果块大小> 1字节又如何?答案: 将内存地址分为三段,分别是18,10,4Valid有效位: 确定在该行中是否存有数据 (当计算机首次启动时,所有的都是invalid)允许内存中的字为“stale脏”Þ 每个块增加一个 dirty位,以表明当该Cache块被替换时,需要更新内存Þ OS在进行输入输出前,刷新cache较大块的优点空间局部性: 如果访问给定字, 可能很快会访问附近的其他字适用于存储程序概念: 如果执行一条指令, 极有可能会执行接下来的几条指令对于线性数组的访问也是合适的更大容量块的缺点大块意味着更大的miss penalty在miss时, 需要花更长的时间从内存中装入新块如果块太大,块的数量就少结果: miss率上升总的来说,应最小化平均访问时间Average Memory Access Time (AMAT)= Hit Time + Miss Penalty x Miss RateHit Time = 从cache中找到并提取数据所花的时间Miss Penalty = 在当前层miss时,取数据所花的平均时间 (包括在下一层也出现misses的可能性)Hit Rate = 在当前cache层找到所需数据的百分比% Miss Rate = 1 - Hit Rate冲突(Conflict) Misses因为两个不同的内存地址映射到相同的cache地址而发生的miss两个块可能不断互相覆盖 (不幸地映射到同一位置)“直接映射caches”的主要问题如何减小这个效果?处理冲突(Conflict) Misses解决方案 1: 增加cache(有限,总会在某处失效Fails at some point) 解决方案 2: 多个不同的块映射到同样的cache索引?全关联Cache优点不存在冲突Misses (因数据可在任何地方)全关联Cache缺点需要硬件比较器来比较所有入口: 如果在cache中有64KB数据, 4B 偏移, 需要16K比较器: 不可行容量有限(Capacity)Misses因为Cache容量有限而产生的miss如果增加cache大小,miss不会发生概括性定义, 只是获得总体概念N路集合关联优点: 即使2路集合关联cache,也能避免很多冲突型(conflict) miss;硬件费用不是很高: 只需要N个比较器块替换策略:直接映射Cache: 当发生miss时,index完全指定某个块可以写到的位置N路集合关联: 当发生miss时,index指定一个集合,块可以写到集合中的任意位置全关联: 块可以写到任意位置LRU: 替换最近使用最少的块 (读或写) 优点: 时间局部性 Þ 最近使用的将来还会使用: 事实上, 这是非常有效的策略缺点: 对于2路集合关联, 容易跟踪(只有一个LRU位); 对于4路或更多路, 需要复杂的硬件和更多时间来跟踪例: 假定Hit Time = 1 cycle,Miss rate = 5%,Miss penalty = 20 cycles计算平均内存访问时间 AMAT平均内存访问时间= 1 + 0.05 x 20= 1 + 1 cycles= 2 cycles二级cache的比较: L1 大小: 数十KBhit time: 一个周期内完成miss rates: 1-5%L2:size: 数百KBhit time: 几个周期miss rates: 10-20%地址空间 每个程序都似乎拥有自己私有的内存. 因此每个程序都对内存有一个自己的视图.允许多个进程同时驻留内存,并受到保护(即不允许一个程序读写另一个程序的内存)虚拟内存(Virtual Memory)硬件提供virtual地址 ->physical地址映射页表是操作系统中的一个数据结构,包含虚拟地址到物理位置间的映射保存这种数据有几种不同的方式,具体是何种方式由操作系统决定。操作系统中运行的每个进程都有自己的页表page table虚拟内存(VM)的动因:1.受保护的共享内存:不同的物理页可以分配给不同的进程 (共享)进程只能访问自己页表中的页面 (保护)2.分离地址空间:由于程序工作在虚拟空间中, 不同的程序可以在相同的地址具有不同的数据/代码!解决碎片问题: 所有块同样大小, 所有的洞都可使用OS 必须在磁盘上为每个进程保留 “交换空间Swap Space”如果有新的进程, ask Operating System若有未使用的页, OS 优先使用他们否则, OS 将内存中一些旧页与磁盘进行交换每个进程有自己的页表(Page Table)将来会加入一些细节, 但Page Table是虚拟内存的基础.虚拟内存的问题:映射每个地址 -> 每个虚拟地址需要通过Page Table访问内存一次 ->Þ一次虚拟内存访问 = 两次物理内存访问 -> SLOW!因为small is fast, 为什么不使用一个虚拟到物理地址转换的小cache来加速变换呢?由于历史的原因, 这个cache被称为TLB从磁盘中将页装入内存的空余块, 使用DMA传送;其间会切换到其他等待运行的进程.当DMA完成时, 得到一个中断(interrupt) 此时进程page table已经更新因此当切换回本任务时, 所需的数据已经在内存中.选定属于某个程序的其他页,如果该页是dirty的,将该页复制到硬盘;如果是干净的 (磁盘中的备份是最新的),直接覆盖内存中的数据;选择剔除的页面遵循一定更新策略 (如, LRU)更新该程序的page table,以反映其内存数据已经移到其他某个地方如果不断在磁盘和内存中进行交换, 称为Thrashing(翻来覆去)虚拟内存的三个好处:1) 变换: 使多进程成为可能只有程序最重要的部分 (“工作集Working Set”) 必须驻留在物理内存中连续数据结构(如栈)需要多少使用多少,当然后来会逐渐增加程序在内存中看起来是连续的, 即使物理内存是杂乱的2) 保护:不同进程互不干扰不同的页可以有自己专门的特性(只读, 用户程序看不见等).用户程序看不见核数据(Kernel data)可以免受“邪恶”程序的侵害 Þ Far more “viruses” under Microsoft Windows进程的特殊模式 (“Kernel mode”) 允许进程改变page table/TLB3) 共享:可以将同一物理页映射给多个用户(“共享内存”);分页是最著名的虚拟内存实现(另一方式是base/bounds);每个分页的虚拟内存访问都必须通过在内存中的Page Table行来进行检查和访问,从而提供了保护/ indirection;Page Table Entries 的Cache (TLB)使得不通过内存访问就能进行地址变换,从而在多数情况下加速了该过程.使用程序的内存视图:连续从某个地址开始无限大是唯一运行的程序实际上:非连续开始于可用内存的任何地方有限大多个程序在运行虚拟内存提供了:连续内存的幻像;所有程序始于同一地址;无限大内存的幻像(232 or 264 bytes);保护.实现:将内存分为 “块” (页);操作系统控制页表,该页表实现虚拟地址到物理地址间的映射;把内存看成是磁盘的cache;TLB是页表的 cache.设备逻辑计算机有两个寄存器:控制寄存器, 表明可以读/写数据(I/O准备好) 就象路边的交警;数据寄存器, 包含数据;当检测到人从键盘输入时,键盘上的电脑,将该“键”的值存入键盘的数据寄存器;然后, 将键盘的控制器Ready位置; 处理器循环读取设备(如键盘)的控制寄存器, 如果发现控制器从变到,说明设备准备好;然后处理器(从输入中)装入(loads)或者写到 (输出)数据寄存器;设备检测到其数据寄存器被取走或者装入,即重置控制寄存器的Ready位(1到0) 读键盘 (接收); 2个设备寄存器写终端(terminal) (发送); 2个设备寄存器读(Receiver): Ready = 1 意即数据寄存器中的字符还未被读取; 写(Transmitter): Ready = 1 意即传送端已准备接收一个新的字符;让处理器花费大量时间等待I/O准备好是极大的时间浪费解决方案: 使用异常机制来帮助I/O. 当I/O准备好后,中断当前正在运行的程序,执行中断程序以传送数据, 数据传送结束后返回例题: 假定处理器为1GHz时钟频率,每次轮检操作花费400个时钟周期 (调用轮检(polling)进程,访问设备, 并返回). 试确定处理器用于polling的时间 %Mouse: 每秒轮检(polled)30次,以便捕获用户移动软盘: 传送数据单位为2字节,传送速度为50KB/秒. 不能丢数据.硬盘: 传送数据单位为16-字节块,传送速度为16 MB/秒. 同样,不能丢数据.Mouse轮检clocks/sec = 30 polls/s * 400 clocks/poll = 12K clocks/s% Processor for poll