开设计算机课程的好处,计算机组成课程如何起到承上启下的作用?

计算机组成原理课程在计算机系统中的位置

图1描述了计算机系统抽象层的转换。从图1可以看出,计算机系统由不同的抽象层构成,“计算”的过程就是不同抽象层转换的过程,上层是下层的抽象,而下层则是上层的具体实现。

图1 计算机系统抽象层的转换

“计算机组成”课程涉及的内容主要位于图1中寄存器传送层(RTL)以上的微结构和ISA层次,介于软件和底层硬件电路之间的交界面上,属于整个计算机学科和计算机系统中最重要的基础核心内容。该课程是计算机专业最重要的专业基础课之一,所涉及的内容除了与数字逻辑电路、嵌入式系统等偏硬件类课程有直接关联外,还与操作系统、编译程序、高级语言程序设计等软件方面的课程密切相关。因而,在整个计算机专业中,该课程起着重要的承上启下的作用。

目前,国内高校的课程设置通常是先开设一门“计算机系统概论”或“计算机科学导论”之类的入门课程,这些课程或者是内容太散太多、没有系统性(只是所有大学课程内容的简单罗列),或者是偏离计算机系统而侧重于可计算理论方面的内容,仅通过学习这类入门课程,学生还不能够很好地建立起完整的计算机系统整机概念,也无法深刻理解计算机系统各抽象层的等价转换关系。

对于与计算机系统核心内容相关的课程,通常是在低年级先开设最上层的“高级语言程序设计”和最下层的“数字逻辑电路”课程,随后开设中间层的“计算机组成”课程,然后是其上层的“操作系统”、“计算机体系结构”和“编译技术”等。显然,对于最上层“高级语言程序设计”和最下层“数字逻辑电路”的教学,因为它们在计算机系统层次中相距较远,很难把它们相互联系在一起,都只能限定在各自局部层次中进行教学。在学习“高级语言程序设计”时,学生无法在程序与机器指令以及机器结构之间建立关联,因而,对程序设计中的许多问题只能一知半解,甚至有些问题根本就无法理解。

同样,在学习“数字逻辑电路”时,也很难让学生把逻辑电路与机器指令以及机器结构建立关联,更不用说能够明白逻辑电路和程序之间的关系了。在“计算机组成”课程教学时,如果把仅它当成一门纯硬件课程,仅将课程内容限定在ISA和微体系结构层,那么,学生还是不能把程序、指令、机器结构和逻辑电路等关联起来,原来需要建立课程之间的关联才能明白的很多重要问题还是无法弄清楚,因此,不能把“计算机组成”当成一门纯硬件课程,需要将它的内容与“高级语言程序设计”和“数字逻辑电路”课程的内容关联起来。同样,“计算机组成”和后续的“操作系统”、“计算机体系结构”和“编译技术”等课程也是密切相关的,如果能够在教学过程中,把它们之间的关联描述清楚,那么将会为后续相关课程的学习打下良好的基础。

“计算机组成”课程在整个计算机系统相关课程链中处于中心位置,该课程教学效果的好坏,对于学生建立计算机系统整机概念和培养学生计算机系统分析、设计、开发和应用能力是至关重要的。该课程应起“粘合剂”的作用,在其教学过程中应将计算机软件和硬件有机结合,应站在高级语言程序员的角度来理解计算机组成与系统结构,通过为程序员描述底层机器级行为来把计算机系统中的各个抽象层联系起来。

本文将详细阐述“计算机组成”与其他相关课程之间的关联,其中,第2节介绍该课程与“高级语言程序设计”课程之间的关联;第3节介绍该课程与“数字逻辑电路”和“计算机体系结构”课程之间的关联;第4节和第5节分别介绍该课程与“操作系统”和“编译技术”课程之间的关联。

2 与高级语言程序设计课程的关联

高级语言程序必须转换为机器语言目标代码才能在计算机中运行,其执行结果虽然由高级语言语句和所处理的数据类型及数据的值来决定,但是,归根到底还是由执行程序的计算机的低层机器级行为来决定的。程序员如果能够很好地了解计算机低层机器级行为特征,了解高级语言中数据、运算、语句、(子)过程和文件操作等在计算机系统中的实现细节,那么,就可以编制出高效的程序,并在程序调试、性能提升、程序移植和健壮性等方面成为编程高手。因此,“计算机组成”课程内容可作为“高级语言程序设计”课程的深入内容。

具体来说,在以下课程内容中可以与高级语言程序设计的相关内容建立关联。

2.1数据的表示和运算

数据的表示和运算是“计算机组成”课程中的基本内容,传统上在该课程中仅介绍各类定点数和浮点数的编码表示,非数值数据的编码表示,以及相应的各种算术运算算法及其运算电路,而很少把这些内容与高级语言程序中处理的数据建立关联,而事实上高级语言程序中的数据就是该课程中所介绍的数据,只是从不同角度看到的数据的属性不同罢了。例如,C语言程序中unsigned型数据就是定点二进制数,int型数据就是定点补码整数,float和double型数据就是IEEE 754单精度和双精度浮点数;C语言中支持的各种运算就是该课程中所介绍的运算电路实现的;各种数据类型的位数就是定、浮点数编码的位数。由于计算机中运算数据通路宽度和其他底层机器结构的限制,使得高级语言程序在进行数据类型转换或特定运算时会出现一些意外结果[3]37-38,45-47,74-75,如果不把高级语言程序中的数据及其运算与低层机器结构及机器级数据的表示建立关联,则很难理解为何会发生这些意外结果。

图2是CMU CS213课程]的第一讲讲义中的一张幻灯片,它说明在计算机系统中int型数据不是现实世界中的整数,浮点数也不是现实世界中的实数,例如,对于现实世界中任意一个整数或实数x,都有xx≥0,但是,在计算机中,某些int型数据并不满足这个结论,例如,当x=50000时,结果会得出xx≤0的结论。再例如,在现实世界中,整数和实数都满足结合律,但是,在计算机中,某些浮点数运算时就不满足结合律,如当x=1e20,y=-1e20,z=3.14时,(x+y)+z=3.14,而x+(y+z)=0,两者不等。

图2 计算机内运算不同于现实世界中运算的例子

如果在教学中除了介绍编码表示以外,还把编码表示与程序设计中遇到的问题结合起来,相信学生会得到更多的收益,也会对“计算机组成”课程的学习更感兴趣。

同样,在讲述数据存放方式时,也可把大端/小端方式与具体程序及指令相关联。程序开发中经常需要将二进制代码显示出来以对程序进行调试,程序员根据数据是按小端还是大端存放,就能通过二进制代码还原数据的真值。同样,程序中的数据也涉及到是对齐还是不对齐存放的问题,在编译器设置的数据对齐方式、高级语言程序中变量的地址(指针)、指令执行时的访存处理过程以及内存模块(内存条)的组织结构之间建立关联,可以让学生从一个对齐存放的小问题中去深刻理解计算机系统各层次之间的关联,而且有了这些认识后,可以在程序设计和程序调试时注意因为数据对齐而出现的意想不到的结果。

2.2 Cache的基本原理

Cache的基本原理是“计算机组成”课程中重要的内容。对这一部分的教学,传统上通常就介绍一下Cache的基本原理和访问局部性,然后介绍三种映射方式和替换算法以及写策略问题。实际上,高级语言程序与Cache之间有非常紧密的联系[3]149-151。虽然从程序员角度来说,编程过程中根本感觉不到Cache的存在,Cache对程序员来说是透明的,但是,由于程序访问的局部性特点,使得引入Cache后可以保证其命中率非常高,从而在绝大多数情况下可以只访问高速的Cache而使CPU访存速度加快,因此,程序设计时是否考虑访问局部性对程序的性能是至关重要的,要做一名高水平的程序员必须深刻理解Cache机制。

因为Cache对程序员透明,所以在程序设计课程中肯定不会涉及到Cache问题。如果在“计算机组成”课程中又不将Cache与程序设计关联的话,学生就不知道在编程时要考虑局部性,从而可能编写出局部性很差的程序,极大降低程序执行性能。

图3是CMU CS213课程的第一讲讲义中的一个例子,说明了求转置矩阵的两种具有同样代码量的不同实现方式,因为其数据访问的局部性的不同,它们的性能在pentium 4上测试的结果相差21倍左右。

图 3 访问局部性对程序性能影响的例子

图3中左边的程序按照数组元素在内存的存放顺序进行访问,因而具有很好的空间局部性,而右边的程序跳跃式访问数组元素,因而空间局部性很差,在其他条件完全一样的情况下,仅仅因为空间局部性的不同就导致了20多倍的性能差异。相信学生通过学习这样的例子,会对Cache与程序设计之间的关系产生深刻的印象,如果再进一步对该例中每个数组元素的访存过程进行详细讲解,那么,对于Cache的工作原理以及访问局部性和Cache之间的关系等原先很难理解的比较抽象的问题,就变得很容易理解了。

实际上,在高级语言程序设计中很多情况下都存在如何开发访问局部性的问题,也有很多程序例子可以用于分析访问局部性和程序性能之间的关系,从而更好地理解Cache基本原理。

2.3虚拟地址空间划分

虚拟存储器是“计算机组成”课程中的重要内容,传统教学只会介绍虚拟存储器的基本概念、页表和页表项,以及页式、段式和段页式三种存储管理方式,很少把虚拟存储器与程序设计的内容进行关联,因此,学生在学习这部分内容的时候,会感到太抽象而不容易理解。例如,对于逻辑地址(即虚拟地址),通常定义为“用户编制程序时所使用的地址”,对于虚拟地址空间,通常解释为“程序员编写程序时所用的统一的地址空间,每个程序都有相同的地址空间”,除此之外不会有更多的解释,这对于学生来说是很难理解的。他们虽然能使用高级语言编制程序,也许还学过如何使用汇编语言编制程序,但是从这些经验里面,他们并不能明白编制程序所使用的地址是什么。

因为高级语言在计算机系统中属于操作系统以上的抽象层,高级语言程序中所使用的地址,不管是代码的地址还是数据的地址,对应用程序员(即上述“逻辑地址”定义中的用户)来说都是感觉不到的;汇编语言虽然在计算机系统中属于较低抽象层,汇编语言程序员可以为代码段和数据段定义地址,但是这个地址并不是我们所说的虚拟地址,因此,即便是学生有用汇编语言编写程序的经验,也无法正确理解“用户编制程序时所用的地址”这样的概念。

正确理解“虚拟地址”这个概念,对于虚拟存储器整个知识点的学习是至关重要的。将虚拟地址空间的划分和程序设计中的相关概念建立关联[3]174-175,有助于学生理解“虚拟地址”概念,对于“所有程序使用相同的地址空间”这句话也就很好理解了,而且,对于学生进一步理解程序设计中涉及到的变量的作用域和寿命等问题也有很大帮助。

图4是在Linux操作系统下hello程序的一个进程对应的虚拟地址空间映像,通过对虚拟地址空间与hello程序各部分之间的对应关系的说明,可以将很多相关概念关联起来,从而使学生能够比较容易地理解许多深层次的问题。

图 4 hello程序对应的Linux虚拟地址空间映像

首先,通过图4可以简要解释程序开发过程中编译链接环节的实现目标以及程序装入过程,为学生对整个程序开发和装入运行过程的理解提供必要的基本知识,也为学生进一步学习操作系统中的存储器管理打下基础。

其次,通过图4还可以让学生理解“程序”和“进程”的本质差别,hello程序是指在磁盘上的hello可执行文件,而一旦通过操作系统“装载程序”在虚拟地址空间中建立了图4所示的存储映像,hello程序就成为了“进程”。

第三,通过图4可以让学生理解操作系统内核空间和用户空间的差别,理解为什么每个进程的用户空间的范围和大小总是一样的,例如图4中显示的用户空间总是在0到0xc0000000之间的区间,每个用户进程的空间都一样。

第四,通过图4可以更好地理解用户空间中的静态区和动态区的概念,从而更加深刻理解程序设计课程所学习过的变量的作用域和寿命的概念。如图4所示,全局静态变量全部分配在只读数据或可读写数据区,这两个区域是静态区,不会被动态覆盖,因而只要进程存在,变量的空间就一直存在,所以它们具有“全局寿命”;而局部动态变量分配在用户栈区,用户栈是由过程调用中每个过程对应的“栈帧”不断地动态生长和消退而形成的[3]216-223(这个概念在本课程其他相关知识点的讲解时建立),因而这类变量的作用域仅局限在所在过程或函数内,并且仅具有限于所在过程或函数的“局部寿命”。

第五,通过图4也能使学生更好地理解存储保护中地址越界和访问越权的概念。可以看出,为了便于存储保护,图4所示的虚拟空间中,程序中的只读数据和所有代码存放在一起,它们具有“不可写”的特性,可读写的静态数据占用固定的区域,它们具有“可读可写”的特性。这为在后续“操作系统”课程中学习相应内容打下了基础。

第六,通过图4可以帮助学生理解程序设计课程中与用户空间的动态分配与释放相关的函数的功能,并且可以了解到虚拟空间中低地址向高地址增长的堆区就是动态分配的空间,这些对学生在后续“操作系统”课程中学习相应的存储管理内容会起到重要的作用,也使学生对存储器泄漏问题的实质有更清楚的认识。

2.4指令系统设计

指令集体系结构(ISA)是计算机系统中最核心的抽象层,位于软件和硬件交界面,因此,指令系统设计是“计算机组成”课程中最核心的内容。传统上这部分教学着重介绍指令系统设计涉及的指令格式、操作码编码、操作类型和寻址方式问题,而不提及指令系统与高级语言之间的关系,事实上,高级语言程序作为指令系统设计的需求,它们之间是密切相关的,高级语言处理的数据及其运算就是指令中的数据及其运算,高级语言语句的实现就是若干条指令构成的指令序列的实现,因此,指令系统设计时,需要从如何满足高级语言中数据及其运算以及各类语句功能的需要出发,从如何解决高级语言功能的问题入手来讲解指令系统相关知识点。

例如,要有效实现选择结构语句需要提供哪些指令?要有效实现循环语句需要提供哪些指令?提供什么样的寻址方式可以方便实现循环体中数组元素的访问?要实现高级语言中的过程(函数)调用需要提供哪些指令以及什么样的寄存器使用协议?过程调用时用户栈中每个过程的栈帧的结构如何规定?所有这些都是指令系统设计的关键,如果讲解指令系统设计内容时不从上述这些问题出发,则学生基本上是只知其然而不知其所以然,了解的只是有关指令系统的一点皮毛,这样的教学对学生专业能力的培养所起的作用不大。

3 与数字逻辑电路和体系结构课程的关联

通常,“数字逻辑电路”在“计算机组成”之前开设,而“计算机体系结构”则在“计算机组成”后面开设,这三门课程的内容位于计算机系统中同一层或相邻层,它们之间存在较大关联。

“计算机组成”与“数字逻辑电路”之间的关联,基本上贯穿所有涉及到微体系结构设计的内容,例如,寄存器(组)、加法器、ALU、乘法器、除法器、BCD码加法器、存储器基本电路、数据通路、控制器、I/O接口电路等,这些功能部件及其定时设计都基于数字逻辑电路基本原理,因而两门课程内容衔接很自然。不过,“计算机组成”与“计算机体系结构”课程之间的关联目前还存在很多问题,一方面两门课重复内容较多,另一方面两门课又有一些内容没有衔接好。

在和“数字逻辑电路”及“计算机体系结构”课程的关联方面,“计算机组成”课程需要在下面几个内容教学时进行改进。

3.1基本运算部件

半加器、全加器和无符号加法器的内容应该是“数字逻辑电路”中的主要内容,包括像SN74181芯片和SN74182芯片等介绍都不应作为”计算机组成”课程的主要内容。特别是现代计算机中的CPU已经集成了像Cache这样的高速缓存,并且内含了多个核处理器,已经早就不需要通过用SN74181和SN74182类似芯片级联形成CPU了,如果在课程教学中涉及到SN74181和SN74182等芯片及其级联等内容的话,其意义仅在于让学生了解现代CPU中是如何用快速的先行进位方式来实现加法器的,而不需要让学生了解如何进行芯片级联,更不能让学生产生错误的认识,以为现代计算机的CPU是由芯片级联形成。

3.2 CPU的组织结构

传统上有关CPU组织的内容都是以总线式CPU作为模型机来进行讲解的,有的是单总线结构模型,有的是双总线或三总线结构CPU模型,这样的模型机实际上都不能反映现实技术,现代CPU中指令的执行都采用高级流水线技术,而总线式CPU连最基本的指令流水线都无法实现,而且指令的执行总是需要多个时钟周期才能完成,相应控制器的设计也比现实更复杂,因此这些内容的传授,并没有让学生了解到CPU的真实结构,也无助于培养学生进行CPU设计的能力,更没有为后续高级课程的学习打下必要的基础,与“计算机体系结构”课程内容之间存在较大鸿沟,学生无法从总线式CPU结构一下子跳跃到“计算机体系结构”课程中的高级流水线CPU结构。

为了与“计算机体系结构”能够很好地衔接和关联,“计算机组成”课程中需要细化指令流水线的执行过程,为此,需要在讲解指令流水线之前给出单周期数据通路及其控制器的结构,然后在单周期处理器的基础上给出流水线处理器的结构,再在流水线处理器中分析一个指令序列中的各指令在指令流水线中每个时钟周期内的数据流动过程,从而为理解指令流水线执行时可能的冒险现象以及解决流水线冒险的处理方法打下良好的基础。

3.3 数据通路的定时

对于数据通路的定时,传统教学都会提到CPU的三级时序信号系统和机器周期的概念,事实上这些概念都是在引入Cache之前的处理器设计中所用的,在现代计算机中它们是过时的一些知识点,不应该作为其主要内容,最多只能作为历史性或过渡性介绍内容。传统教学中很少有对现代计算机中数据通路定时方式的介绍,而这个内容却是非常重要的,它是学生理解时钟周期和主频以及计算机性能等内容的基础,需要在教学中增加这部分内容。

3.4 微程序控制器的设计

传统教学中通常把微程序控制器设计的内容作为重要的部分来讲,但是,现代计算机中即使是CISC处理器,其微体系架构也都采用RISC思想,将指令转换为类似RISC指令的微操作来实现,因此那种与复杂指令对应的微程序的设计应该变得不重要了。

4 与操作系统课程的关联

“操作系统”是“计算机组成”的后续课程。因为“操作系统”主要内容是如何管理计算机中的资源,而“计算机组成”课程所介绍的正好就是这些计算机中的资源,如CPU、存储器和I/O,而且操作系统需要通过硬件提供的特权指令直接对硬件底层进行控制和处理,因而这两门课程内容之间存在非常密切的关联。

这两门课程之间的关联主要体现在以下几个方面。

4.1 异常和中断处理

异常和中断是打断用户进程正常执行的两大类事件,它们的发生会引起CPU从执行用户进程的用户模式转入执行系统进程的内核模式。有关中断和异常的概念在两门课程中都是重点内容,因为两门课程都涉及到同样的内容,所以,需要对学生交代清楚:对“计算机组成”和“操作系统”来说应该各自关注哪些方面,也就是要在这两门课程之间给出一个比较清晰的接口,让学生明确整个异常和中断机制中哪些是需要硬件实现的功能,哪些是需要操作系统实现的功能。

目前在“计算机组成”课程传统教学中,基本上沿用Intel 8086/8088中的说法,把内部异常(exception)和外部中断(Interrupt)统称为中断,并把中断处理的相关内容基本上都放到输入/输出系统部分进行讲解。在对异常和中断部分的教学过程中,基本不会提到与操作系统及CPU运行模式等内容的关联,很少关注内部异常和外部中断之间的本质差别,特别是没有把有关异常和中断的检测及响应过程放到指令执行过程中去讲解,因而学生很难理解隐指令的本质含义,很难理解“异常和中断的检测与响应由硬件执行”这句话的实际含义,更无法理解指令流水线中的异常和中断机制以及精确中断和非精确中断的含义。因为“计算机组成”课程的传统教学中,没有引入CPU运行模式的概念,所以学生无法得到对很多关键问题的正确认识,例如,异常和中断如何引起CPU模式的切换?硬件需要为此提供哪些机制?硬件和操作系统之间是如何协调处理异常和中断的?中断(异常)返回指令与过程返回指令功能的差别以及它们各自在数据通路中的执行过程是什么?

本文认为,为了更好地与操作系统中相应内容衔接,在“计算机组成”课程中应该增加或强化以下内容:严格区分内部异常和外部中断,并将内部异常的内容放在对CPU数据通路和控制器进行介绍的部分,通过分析具体指令执行过程中可能的异常事件来强化内部异常的概念,并通过例子来说明异常响应过程的具体操作,同时引入CPU运行模式,将异常响应过程与模式切换结合起来,在操作系统课程教学时再重温回顾这部分内容并细化操作系统内核中相应的处理细节,这样,学生可以非常清晰地了解整个过程,包括相关的硬件和软件部分。

对于异常和中断,“计算机组成”和“操作系统”两门课程各自的侧重点不同,前者应更侧重于异常和中断的识别检测及响应,对异常和中断处理只要简单提一下框架即可,而后者更侧重于异常和中断的处理,特别是针对不同异常类型和不同设备中断的处理流程以及处理前的准备工作流程和处理后的恢复及返回工作流程。

4.2 虚拟存储器机制

“计算机组成”和“操作系统”课程中都涉及到虚拟存储器,传统教学在这两门中所讲的内容很多都是重复的,例如,两门课程都会讲三种虚拟管理方式,地址转换、页表和页表项、TLB等,如果不特别强调硬件和操作系统各自在实现虚拟存储机制中的角色,就会给学生带来困惑,不知道哪些内容属于硬件设计时需要考虑的,哪些是操作系统需要考虑的。

在“计算机组成”课程传统教学中,很少提及操作系统是如何介入虚拟存储管理机制的,而在“操作系统”课程教学中也很少明确告诉学生在虚拟存储管理中硬件和操作系统之间的接口在哪里,学生很难建立“地址转换是由CPU在执行指令时完成的”这样的概念,也很难明白“操作系统可借助于一种特殊的异常事件—缺页来介入虚拟存储管理”,更不容易明白“TLB缺失处理可以用软件实现也可以用硬件实现”的道理。而上述这些都是关于计算机系统能力的非常重要的内容。

在关于虚拟存储器内容的教学中,正如本文2.3节中所述,首先要讲清楚虚拟地址空间的概念,然后,在此基础上把虚拟存储管理中最重要的“按需分页”的基本思想说清楚,从而引入页表和页表项的概念,最后把地址转换放到一条指令的执行过程中来介绍,以强化地址转换是由硬件执行这样的概念,在介绍地址转换过程时,再把硬件与操作系统之间的关联讲清楚。让学生明白“缺页”、“地址越界”和“访问越权”等需要操作系统介入的异常事件是由CPU在执行指令过程中进行地址转换时发现的,这些事件是与存储管理相关的异常事件,像上述4.1节所述,在遇到这些异常事件时,会发生CPU执行模式的切换,使CPU从执行用户进程的用户态转入内核态执行,在内核态中CPU可以执行特权指令并访问操作系统内核存储区,因而通过把页表保存在操作系统内核地址空间,操作系统内核就可更新页表,并防止用户进程改变页表,从而确保用户进程只能访问由OS分配给的用户地址空间。

通过将虚拟存储管理与指令执行关联起来讲解可以非常具体地说明计算机系统中硬件和操作系统之间协调完成特定任务的过程。

同样,介绍TLB工作原理时也可以与指令的执行过程进行关联,让学生了解TLB缺失也是由CPU在执行指令过程中进行进行地址转换时发现的,如果用硬件实现对TLB缺失的处理,那么就像Cache缺失处理一样,CPU冻结当前指令的执行时序,即当前正在执行的指令被阻塞,转到相应的缺失处理控制逻辑去执行,结束后再回到当前被冻结的指令进行执行;如果用软件实现对TLB缺失的处理,那么就像缺页处理一样,会引起CPU执行模式的切换,调出操作系统内核进行相应处理。

4.3 系统控制类指令的设计

在“计算机组成”课程中讲解指令系统的设计时,都会提到指令系统中有系统控制类指令,但是对于具体有哪些指令则很少提到。事实上,这些系统控制类指令主要用于操作系统内核程序,并且与机器底层的控制有关,例如,操作系统在进程切换时,需要冲刷Cache和TLB,因此,会有一些与Cache和TLB管理相关的系统控制类指令;自陷和系统调用是从用户态向核心态转换的其中一种方式,因此,指令系统设计时需要有自陷指令和系统调用指令。如果在讲到相关内容时,提一下系统控制类指令与进程切换和CPU模式转换等的关系,也可以为学生学好操作系统打下良好的基础。

4.4 输入/输出系统

在“计算机组成”课程中,通常会有一个专门的章节来介绍I/O系统,而操作系统与I/O系统有着极其密切的关系。OS在I/O系统方面的职责主要由I/O系统的三个特性决定的。

(1)共享性:指I/O系统被处理器执行的多个程序共享,因此I/O系统应该由OS统一调度管理,以保证用户程序只能访问自己有权访问的那部分I/O设备,并对共享的I/O资源提供合理的调度管理,使系统的吞吐率达到最佳。

(2)复杂性:指I/O设备控制的细节比较复杂,不能由上层用户程序来实现,需要OS提供专门的驱动程序来控制,以对用户程序屏蔽设备控制的细节,简化用户程序的编写。

(3)“中断”式交互性:指外部设备请求CPU介入时只能使用中断方式,请求的目的是希望处理器执行专门的输入/出程序来完成外设与主机的数据交换,或希望处理器执行像打印机缺纸这种特殊事件处理程序。像上述4.1节所述,中断导致用户态向操所系统内核态转移,因此,各种具体的中断处理过程由OS来实现。

在操作系统的设备管理程序、设备驱动程序和中断服务程序中都涉及到关于I/O设备、I/O接口和I/O控制方式等内容,而这些是“计算机组成”课程的基本内容,在讲解这部分内容时如果能有意识地说明和操作系统之间的关联,将会为学生学习后续操作系统课程打下良好基础。MIT6.004课程[5](Computation Structures,相当于国内的计算机组成课程)的实验8设计的实验内容很有启发性,它非常恰当地表达了“计算机组成”和“操作系统”两个课程与输入/输出系统之间的关系,对学生理解用户是如何从用户进程陷入到操作系统,最终由操作系统内核直接控制输入/输出设备这样的过程很有帮助。

5 与编译技术课程的关联

“计算机组成”是“编译技术”课程的先行课程。因为编译器的功能是将高级语言程序转换为机器级程序,而机器级程序(即汇编指令序列或机器指令序列)的相关内容以及执行机器级程序的机器的相关内容就是“计算机组成”课程讲解的主要内容,因此,“计算机组成”和“编译技术”之间也有很大关联。在“计算机组成”课程教学时,可以在以下几个方面与编译程序建立关联。

5.1 程序的等价翻译转换

在“计算机组成”第一讲中通常会通过程序功能等价转换的例子来阐述计算机系统层次结构,在这里可以通过例子让学生初步了解编译程序的概念。然后,在后续相关内容的讲解中,只要遇到用高级语言程序举例说明时,都强调是经过编译后得到的对应机器级程序,并强调选择哪个寄存器来存放高级语言程序变量是编译器的工作,选择什么样的指令序列来实现特定高级语言程序功能也是编译器的工作,由此来强化编译程序与“计算机组成”相关内容之间的关联,潜移默化地强化学生的计算机系统整体概念。

5.2 流水线调度与编译优化

在“计算机组成”课程中涉及到指令流水线设计,其中的数据冒险和控制冒险的处理以及静态和动态流水线调度等内容都与编译优化有关,在介绍这些内容时,可以通过例子来说明编译优化的概念。因为在“编译技术”课程中不会涉及计算机结构和指令系统,因而这方面的编译优化技术不可能在这门课中介绍,因此安排在“计算机组成”或“计算机体系结构”课程中讲解比较适合。

6 结语

“计算机组成”课程内容位于计算机系统最核心的中间位置,它对学生建立计算机系统整体概念,对培养学生深刻理解、使用、设计和开发计算机系统起着非常重要的作用。在该课程的教学过程中,如果能够很好地把它和高级语言程序设计课程内容建立关联,它将能起到为“高级语言程序设计”课程解疑答惑的作用,强化学生在程序调试、程序性能提升、程序移植和程序健壮性等方面的能力。在与“数字逻辑电路”和“计算机体系结构”课程的衔接中,还需要更加合理地安排内容,减少重复的和陈旧的内容,增加必要的过渡内容。在与“操作系统”课程的关联部分,需要把硬件实现部分和操作系统实现部分区分开来,侧重讲清楚硬件实现部分以及硬件与操作系统之间的接口部分,而把操作系统实现的部分留给操作系统课程。在与“编译技术”课程的关联中,着重让学生了解编译程序与机器结构及指令系统的密切关系,并建立编译优化和指令流水线技术的关联。

作者袁春风,南京大学计算机系教授。

你可能感兴趣的:(开设计算机课程的好处)