笔记:《现代操作系统》第一章 引论

计算机科学和许多领域一样,主要是由技术驱动的。古罗马人缺少汽车的原因不是因为他们非常喜欢步行,是因为他们不知道如何造汽车。个人计算机的存在,不是因为数以百万计的人有着迫切的愿望—拥有一台计算机,而是因为现在可以很便宜地制造它们。

1、关于什么是操作系统

(1) 操作系统是一种运行在内核态的软件。内核态是计算机的一种运行模式,在这种模式下,操作系统具有对所有硬件的完全访问权,可以执行机器能够运行的任何指令。还有一种运行模式是用户态,在用户态下,只使用了机器指令中的一个子集。

(2) 操作系统的任务是为用户程序提供一个更好、更简单、更清晰的计算机模型,并管理计算机中的所有设备(处理器、主存、磁盘等等)。

(3) 操作系统运行在裸机之上,为所有其他软件提供基础的运行环境。

(4) 操作系统的两大作用:

作为资源管理者,操作系统的任务是有效地管理系统的各个部分,在相互竞争的程序之间有序地控制对处理器、存储器以及其他I/O接口设备的分配; 或是记录哪个程序使用什么资源、对资源请求进行分配,评估使用代价,并且为不同的程序和用户调解互相冲突的资源请求。

作为扩展机器,操作系统的任务是为用户提供比实际机器更便于运用的抽象,这些抽象包括进程、地址空间以及文件等,也即隐藏硬件,呈现给程序(以及程序员)良好、清晰、优雅、一致的抽象。

2、关于第一台计算机和第一位程序员

第一台真正的数字计算机是英国数学家Charles Babbage(1792-1871)设计的。它是一台纯机械的数字计算机,Babbage认识到他的机器需要软件,所以他雇佣了一个名为Ada(艾达)的年轻妇女,她是世界上第一个程序员。程序设计语言Ada是以她命名的。

3、计算机硬件简介

(1) 处理器(CPU)

处理器从内存中取出指令并执行。在每个CPU基本周期中,首先从内存中取出指令,解码以确定其类型和操作数,接着执行,然后取指令、解码并执行下一条指令。按照这一方式循环,直到程序被执行完成。

每个CPU都有一套可执行的专门指令集。由于用来访问内存以得到指令或数据的时间比执行指令花费的时间长的多,因此,所有CPU内都有一些用来保存关键变量和临时数据的寄存器。

几种寄存器的介绍:

程序计数器:它保存了将要取出的下一条指令的内存地址。在指令取出后,程序计数器就被更新以便指向后继的指令。

堆栈指针:它指向内存中当前栈的顶端。该栈包含了每个执行过程的栈帧,栈帧中保存了输入参数、局部变量、临时变量等信息。

程序状态字(Program Status World, PSW):包含了CPU优先级、模式(用户态或内核态),以及各种控制位等。在系统调用和I/O操作中,PSW的作用很重要。

为了从操作系统获得服务,用户程序必须使用系统调用以陷入内核并调用操作系统。TRAP指令把用户态切换成内核态,并启用操作系统。当工作完成后,在系统调用后面的指令把控制权返回给用户程序。

多线程允许CPU保持两个不同的线程状态,然后在纳秒级的时间尺度内来回切换。多线程不提供真正的并行处理,在一个时刻只有一个进程运行,但是线程的切换时间则减少到纳秒数量级。多线程对操作系统而言是有意义的,因为每个线程在操作系统看来就像是单个的CPU。

GPU(Graphics Processing Unit): 指的是由成千上万个微核组成的处理器,擅长处理大量并行的简单计算,比如图像渲染等。但是不适合串行任务。

(2)存储器

理想情况下:存储器应该极为迅速(快于执行一条指令,这样CPU不会受到存储器的限制),充分大,并且非常便宜。

典型的存储器层次结构为:

 寄存器
 高速缓存
 主存
 磁盘

按照序号排列,访问速度从快到慢,容量从小到大,价格从低到高。

寄存器:存储器系统的顶层,与CPU的材料相同,所以和CPU一样快。

高速缓存:多数由硬件控制。主存被分割为高速缓存行(cache line),其典型大小为64字节,地址0至63对应高速缓存行0,地址64至127对应高速缓存行1,以此类推。最常用的高速缓存行放置在CPU内部或者非常接近CPU的高速缓存中。

高速缓存命中:当某个程序需要读取一个存储字时,高速缓存硬件检查所需要的的高速缓存行是否在高速缓存中。如果是,称为高速缓存命中,缓存满足了请求,就不需要通过总线把访问请求送往主存。

高速缓存命中通常需要两个时钟周期。高速缓存未命中就必须访问内存,这样会付出大量的时间代价。

现代CPU中设计两个缓存:

第一级或称为L1缓存:常驻CPU中,通常用来将已解码的指令调入CPU的执行引擎。对于频繁使用的数据字,多数芯片安排有第二个L1缓存,典型的L1缓存大小为16KB。

L2缓存:用来存放近来使用过的若干兆字节的内存字。

L1缓存和L2缓存之间的差别在于时序,对于L1缓存的访问,不存在任何时延;而对L2缓存的访问,则会时延1或2个时钟周期。

主存:又称为随机访问存储器(Random Access Memory, RAM) ,易失性随机访问存储器,断电后存储内容不保存。

只读存储器(Read Only Memory, ROM): 非易失性随机访问存储器,不会丢失其内容。在计算机中,用于启动计算机的引导加载模块就存放在ROM中。

闪存(Flash Memory): 非易失性,可擦除和重写。

(3)磁盘

磁盘驱动器的组成:读/写头(每个盘面1个)、磁盘臂、盘面

磁盘唯一的问题是随机访问数据时间大约慢了三个数量级。其低速的原因是因为磁盘是一种机械装置。

固态硬盘: 不是磁盘,并没有可移动的部分,数据是存储在闪存中的,与磁盘唯一的相似之处就是它也存储量大量即使在电源关闭时也不会丢失的数据。

虚拟内存:通过在RAM和磁盘中反复移动信息块的方式,提供了运行比机器物理内存大的程序的能力。即将程序放在磁盘上,而将主存作为一种缓存,用来保存最频繁使用的部分程序。这种机制需要快速地映像内存地址,以便把程序生成的地址转换为有关字节在RAM中的物理地址,这种映像由CPU中的一个称为存储器管理单元(Memory Management Unit, MMU)的部件来完成。

上下文切换:在多道程序系统中,从一个程序切换到另一个程序,称为上下文切换。此时会对于来自缓存的所有修改的块进行写回磁盘操作,并修改存储器管理单元中的映像寄存器。这种操作带来的时间消耗是比较大的。

(4)I/O设备

I/O设备一般包括两个部分:设备控制器和设备本身。

设备控制器是插在电路板上的一块芯片或一组芯片,这块电路板物理地控制设备。控制器的任务是为操作系统提供一个简单的接口(其实仍然是比较复杂的),它从操作系统接收命令。

为了完成一些工作,在控制器中经常安装一个小的嵌入式计算机,该嵌入式计算机运行为执行这些工作而专门编好的程序。

每类设备控制器都是不同的,所以,需要不同的软件进行控制。专门与控制器对话,发出命令并接受响应的软件,称为设备驱动程序(device driver)。每个控制器厂家必须为所支持的操作系统提供相应的设备驱动程序。

热插拔设备,诸如USB等,需要动态可装载设备驱动程序,即操作系统能够在运行时接收新的设备驱动程序并且立即将其安装好,无须重启系统。

实现输入/输出的三种方式

第一种:用户程序发出一个系统调用,内核将其翻译成一个对应设备驱动程序的过程调用。然后设备驱动程序启动I/O并在一个连续不断的循环中检查该设备,看该设备是否完成工作。若设备可用,则设备驱动程序把数据送到指定的位置,并返回。然后操作系统将控制返回给调用者。因为需要不断检查设备是否可用,会一直占据CPU,轮询设备直到对应的I/O操作完成。这种方式称为忙等待(busy waiting)

第二种:设备驱动程序启动设备并且让该设备在操作完成时发出一个中断。设备驱动程序在这个时刻返回。操作系统接着在需要时阻塞调用者并安排其他工作进行。当设备驱动程序检测到该设备的操作完毕时,它发出一个中断通知操作完成。

中断处理过程:一旦CPU决定处理中断,通常程序计数器和PSW(程序状态字)就被入压入到当前堆栈中,并且CPU被切换到内核态。中断控制器把设备的编号放在总线上,CPU可以读总线,并且知道那个设备完成了操作。设备编号可以成为部分内存的一个引用,用于寻找该设备中断处理程序的地址。这部分内存称为中断向量。当中断处理程序(中断设备的设备驱动程序的一部分)开始后,它取走已入栈的程序计数器和PSW,并保存,然后查询设备的状态。在中断处理程序全部完成之后,它返回到先前运行的用户程序中尚未执行的头一条指令。

中断处理过程简化:

 中断 
 进入内核态 
 操作系统将I/O操作分派给处理程序(即中断处理程序)
 I/O操作完成
 返回用户态
 继续执行下一条指令

第三种:为I/O使用一种特殊的直接存储器访问(Direct Access Memory,DMA)芯片,它可以控制在内存和某些控制器之间的位流,而无须持续的CPU干预。CPU对DMA进行设置,说明需要传送的字节数、有关的设备和内存地址以及操作方向,接着启动DMA。当DMA芯片完成时,它引发一个中断,中断处理过程如上所述。

如果有多个设备发出了中断信号,中断控制器会决定先处理哪个中断,者通常取决于事先赋予每个设备的静态优先级。最高优先级的设备赢得竞争并且首先获得服务,其他设备必须等待。

4、计算机启动过程简述

每台计算机上有一块双亲板,板上有一个称为基本输入输出系统(Basic Input Output System, BIOS)的程序。在BIOS内有底层I/O软件,包括读键盘、写屏幕等其他过程。BIOS放在一块闪存(非易失性)中,操作系统可以更新或升级BIOS程序。

在计算机启动后,BIOS开始运行,它首先检查所安装RAM数量,键盘和其他设备是否安装并正常相应。接着,扫描总线并找出连在上面的设备。如果现有的设备和系统上一次启动时的设备不同,则新的设备将被配置。

然后,BIOS读取存储在CMOS存储器汇总的设备清单决定启动设备。用户可以在系统刚启动时,进入BIOS配置程序,对设备清单进行修改。启动设备上的第一个扇区被读入内存并执行。这个扇区中包含一个对保存在启动扇区末尾的分区表检查的程序,以确定哪个分区是活动的。然后,从该分区读入第二个启动装载模块。来自活动分区的这个装载模块读入操作系统,并启动之。

操作系统启动后,操作系统会询问BIOS,以获得配置信息,对于每种设备,系统检查对应的设备驱动程序是否存在。如果没有,系统要求用户提供驱动程序,一旦有了全部的设备驱动程序,操作系统就将它们调入内核。然后初始化有关表格,创建需要的任何背景进程,并在每个终端上启动登录程序或GUI(图形用户界面)

5、操作系统概念

(1)进程

进程本质上是正在执行的一个程序。

进程的地址空间:一个存储位置的列表。进程可以读写该地址空间。该地址空间中存放有可执行程序程序的数据以及程序的堆栈

与每个进程相关的还有资源集,通常包含寄存器(程序计数器和堆栈指针)、打开的文件清单、突出的报警、有关进程清单,以及运行该程序所需要的所有其他信息。进程基本上是容纳运行一个程序所需要的所有信息的容器。

在许多操作系统当中,与一个进程有关的所有信息, 除了该进程自身地址空间的内容以外,均存放在操作系统的一张表中,称为进程表,进程表是数组(或链表)结构,当前存在的每个进程都要占用其中的一项。

一个挂起的进程包括:进程的地址空间,以及对应的进程表项(其中包括寄存器以及稍后重启动该进程所需要的许多其他信息)。

(2)文件

操作系统的一项主要功能是隐藏磁盘和其他I/O设备的细节特性,提供给程序员一个良好、清晰的独立于设备的抽象文件模型。

为了提供保存文件的地方,大多数操作系统支持目录的概念。

在读写文件之前,首先要打开文件,检查其访问权限。若权限许可,系统将返回一个小整数,称作文件描述符(file descriptor),供后续操作使用。若禁止访问,系统则返回一个错误码。

UNIX系统中,mount系统调用允许把CD-ROM上的文件系统连接到程序所希望的根文件系统上。

UNIX中的特殊文件:

块特殊文件(block special file):由可随机存取的块组成的设备,如磁盘等。程序可以直接访问设备的任意位置,而不必考虑存放该文件的文件系统结构。

字符特殊文件:用于打印机、调制解调器和其他接收或输出字符流的设备。

提供特殊文件是为了使得I/O设备看起来像文件一般。这样,就像使用系统调用读写文件一样,I/O设备也可通过同样的系统调用进行读写。

6、系统调用

任何单CPU计算机一次只能执行一条指令。如果一个进程正在用户态运行一个用户程序,并且需要一个系统服务,比如从一个文件中读取数据,那么它就必须执行一个陷阱(TRAP)或系统调用指令,将控制转移给操作系统。操作系统接着通过参数检查找出所需要的调用过程。然后,它执行系统调用,并把控制返回给在系统调用后面跟随着的指令。

在某种意义上,进行系统调用就像进行一个特殊的过程调用,但是只有系统调用可以进入内核,而过程调用不能。

TRAP指令与过程指令的差别:首先,TRAP指令的副作用是,切换到内核态。而过程调用指令并不改变模式。其次,TRAP指令不能跳转到任意地址上。根据机器的体系结构,或者跳转到一个单固定地址上,或者指令中有一8位长的字段,它给定了内存中一张表格的索引,这张表格含有跳转地址。

在UNIX中,fork是唯一可以在POSIX中创建进程的途径。

在UNIX中,进程将其存储空间划分为三段:正文段、数据段、以及堆栈段。数据向上增长而堆栈向下增长,夹在中间的是未使用的地址空间。堆栈在需要时自动地向中间增长。

7、操作系统结构

客户端-服务器模式是一种可以应用在单机或者网络机器上的抽象。其中服务器提供某种服务,客户端使用这些服务。客户端和服务器之间的通信是消息传递。

虚拟机:裸机硬件的精确复制品。这个复制品包含了内核态/用户态,I/O功能、中断以及其他真实硬件所应该具有的全部内容。由于每台虚拟机都与裸机相同,所以在每台虚拟机上都可以运行一台裸机所能够运行的任何类型的操作系统。

在某些CPU上,试图在用户态执行特权指令时,会被忽略掉。这种特性使得在这类硬件中无法实现虚拟机。

内核中的机制与策略分离原则:考虑一个进程调度的例子,对每个进程赋予一个优先级,并让内核执行具有最高优先级的进程。这里,机制(在内核中)就是寻找最高优先级的进程并运行之。而策略(赋予进程优先级)可以由用户态中的进程完成。在这种方式中,机制和策略是分离的,从而使系统内核变得更小。

操作系统的运行模型:在操作系统二进制代码链接完成后,计算机就可以重新启动,新的操作系统开始运行。一旦运行,系统会动态调入那些没有静态包括在二进制代码中的模块,如设备驱动和文件系统。在运行过程中,操作系统可能由若干段组成,有文本段(程序代码)、数据段和堆栈段。文本段通常是不可改变的,在运行过程中不可修改。数据段开始时有一定的大小,并用确定的值进行初始化,但是随后就被修改了,其大小随需要增长。堆栈段初始化为空,但是随着对函数的调用和从函数返回,堆栈段时时刻刻在增长和缩小。通常文本段放置在接近内存底部的位置,数据段在其上面,这样可以向上增长。而堆栈段处于高位的虚拟地址,具有向下增长的能力,不过不同系统的工作方式各有差别。

在所有情形下,操作系统代码都是直接在硬件上运行的。

整理的大多数是书中的重点知识。

谢谢阅读。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章