Skip to content

概论

操作系统的结构

多道程序设计:通过安排作业(编码与数据)使得 CPU 总有一个执行作业,从而提高 CPU 利用率

分时系统(或多任务):是多道程序设计的自然延伸。对于分时系统,虽然 CPU 还是通过切换作业来执行多个作业,但是由于切换频率很高,用户可以在程序运行时与其交互。

分时系统要求计算机系统是可交互的,以便用户与系统直接通信。用户通过输入设备,如键盘、鼠标、触控板、触摸屏等向操作系统或程序发出指令,并等待输出设备的即时结果。相应的 ,响应时间应当较短,通常小于 1 秒。

分时操作系统允许许多用户同时共享一台计算机。由于分时系统的每个动作或命令往往较短,因而每个用户只需少量 CPU 时间。随着系统从一个用户切换到另一个用户,每个用户都会感到 整个系统只为自己所用,尽管它事实上为许多用户所共享。

操作系统的执行

双重模式

为了确保操作系统的正确运行,必须区分操作系统代码和用户代码的执行。大多数计算机系统采用硬件支持,以便区分各种执行模式

至少需要两种单独运行模式:用户模式内核模式(也称为监视模式、系统模式或特权模式)。计算机硬件可以通过一个模式位来表示当前模式: 内核模式(0)和用户模式(1)。有了模式位,就可区分为操作系统执行的任务和为用户执行的任务。当计算机系统执行用户应用时,系统处于用户模式。然而, 当用户应用通过系统调用,请求操作系统服务时,系统必须从用户模式切换到内核模式,以满足请求

大多数的当代操作系统,如 Windows、UNIX 和 Linux,都利用来双重模式的优点,并为操作系统提供了更强保护

定时器

操作系统应该维持控制 CPU,防止用户程序陷入死循环,或不调用系统服务并且不将控制返给操作系统。为了实现这一目标,可以使用定时器。定时器 可设置为在指定周期后中断计算机。

定时器可以防止用户程序运行过长。一种简单方法是,采用程序允许执行的时间来初始化计数器。例如,能运行 7 分钟的程序可以将计数器设置为 420. 定时器每秒产生一次中断,计数器相应递减 1.只要计数器的值为正,控制就返回到用户程序。当计数器的值为负时,操作系统就会中止程序执行, 因为它超过来设置的时间限制。

进程管理

进程为了完成任务,需要一定的资源,包括 CPU 时间、内存、文件、I/O设备等。这些资源可以在进程创建时赋予,也可以在执行进程时分配。

进程是系统的工作单元。系统由多个进程组成,其中有的是操作系统进程(执行系统代码),其他的是用户进程(执行用户代码)

内存管理

内存是现代计算机系统执行的中心。内存是一个大的字节数组,大小从数十万到数十亿。每个字节都有地址。内存是个快速访问的数据仓库,并为 CPU 和 I/O 设备所共享。中央处理器在获取指令周期时从内存中读取指令,而在获取数据周期时对内存数据进行读写(在冯诺伊曼架构上)。内存一般是 CPU 所能 直接寻址和访问的、唯一的、大容量的存储器。例如,如果 CPU 需要处理磁盘数据,那么这些数据必须首先通过 CPU 产生的 I/O 调用传到内存。同样, 如果 CPU 需要执行指令,那么这些指令必须在内存中

如果一个程序需要执行,那么它必须映射到绝对地址,并且加载到内存。随着程序执行,进程可以通过产生绝对地址来访问内存的程序指令和数据。 最后,程序终止,它的内存空间得以释放,这样下一个程序可以加载并得以执行

为改进 CPU 的利用率和用户的计算机响应速度,通用计算机应在内存中保留多个程序,这就需要内存管理

操作系统管理内存的以下活动:

  • 记录内存的哪部分在被使用以及被谁使用
  • 决定哪些进程(或其部分)会调入或调出内存
  • 根据需要分配和释放内存空间

存储管理

高速缓存

高速缓存有时也简称为缓存,是计算机系统的一条重要原理。它的工作原理如下:信息通常保存在一个存储系统中(如内存), 使用时,它会临时复制到更快存储系统,即高速缓存;当需要特定信息时,首先检查它是否处于高速缓存,如果是,可以直接 使用高速缓存的信息,如果否,就使用位于源地的信息,同时将其复制到高速缓存以便下次再用

位图

位图为 n 个二进制位的串,用于表示 n 项的状态。例如,假设有若干资源,每个资源的可用性可用二进制数字来表示:0 表示 资源可用,而 1 表示资源不可用(或相反)。位图的第 i 个位置与第 i 个资源相关联。例如有如下位图:

1
001011101

第 2、4、5、6 和 8 个资源是不可用的,第 0、1、3 和 7 个资源是可用的

当需要表示大量资源的可用性时,通常采用位图。磁盘驱动器就是这么工作的。一个中等大小的磁盘可以分成数千个单元,称为磁盘块。每个 磁盘块的可用性就可通过位图来表示

系统调用

系统调用提供操作系统服务接口。这些调用通常以 C 或 C++ 编写,当然,对某些底层任务(如需直接访问硬件的任务),可能 应以汇编语言指令编写

通常,系统每秒执行成千上万的系统调用

对大多数的程序设计语言,运行时支持系统(由编译器直接提供的函数库)提供了系统调用接口,以链接到操作系统的系统调用。 系统调用接口截取 API 函数的调用,并调用操作系统中的所需系统调用。通常,每个系统调用都有一个相关数字,而系统调用接口 会根据这些数字建立一个索引列表。系统调用接口就可调用操作系统内核中的所需系统调用,并返回系统调用状态与任何返回值

调用者无需知道如何实现系统调用,而只需遵循 API,并知道在调用系统调用后操作系统做了什么

系统调用的类型

进程控制
  • 结束(end())、中止(abort())
  • 加载(load())、执行(execute())
  • 创建进程(create_process())、终止进程(terminate_process())
  • 获取进程属性(get_process_attributes())、设置进程属性(set_process_attributes())
  • 等待时间(wait_time())
  • 等待事件(wait_event())、信号事件(signal_event())
  • 分配和释放内存(acquire_lock(), release_lock())
文件管理
  • 创建文件(create())、删除文件(delete())
  • 打开(open())、关闭(close())
  • 读(read())、写(write())、重新定位(reposition())
  • 获取文件属性(get_file_attributes())、设置文件属性(set_file_attributes())
  • 文件的移动(move())和复制(copy())
设备管理
  • 请求设备、释放设备
  • 读、写、重新定位
  • 获取设备属性、设置设备属性
  • 逻辑附加或分离设备
信息维护
  • 获取时间或日期、设置时间或日期
  • 获取系统数据、设置系统数据
  • 获取进程、文件或设备属性
  • 设置进程、文件或设备属性
通信
  • 创建、删除通信连接
  • 发送、接收信息
  • 传送状态信息
  • 附加或分离远程设备
保护

保护提供控制访问计算机的系统资源的机制。过去,只有多用户的多道计算机系统才要考虑保护。 随着网络和因特网的出现,所有的计算机(从服务器到手持移动设备)都应考虑保护

通常,提供保护的系统调用包括 set_permission() 和 get_permission(),用于设置 资源(如文件和磁盘)权限。系统调用 allow_user() 和 deny_user() 分别用于允许和拒绝特定用户访问某些资源

系统引导

加载内核以启动计算机的过程,称为系统引导。大多数计算机系统都有一小块代码,称之为引导程序引导加载程序。 这段代码能够定位内核,并加载到内存以开始执行。有的计算机系统(如 PC)采用两个步骤:一个简单引导程序从磁盘上调入一个更 复杂的引导程序,而后者再加载内核

当 CPU 收到一个重置事件时,例如上电开机或重新启动,指令寄存器会加载某个预先定义的内存位置,并从该位置开始执行。 该位置就是初始引导程序所在。该程序为只读存储器(Read-Only Memory, ROM) 形式,因为系统启动时 RAM 处于未知状态

引导程序可以完成一系列任务。通常,有一个任务需要运行诊断程序来确定机器状态。如果通过诊断,则程序可以继续启动步骤。引导 程序也能初始化系统的所有方面:从 CPU 寄存器到设备控制器以及内存内容。最终,它启动操作系统。

有些系统,如手机、平板电脑和游戏控制器,将这个系统保存在 ROM 中。对于小型的操作系统、简单的支持硬件和耐用的操作, 将操作系统存储在 ROM 中是适合的。该方法有一个问题:改动引导程序代码需要改动 ROM 芯片。为了解决这个问题,有些系统 采用可擦可编程只读存储器(Erasable Programmable Read-Only Memory, EPROM),这是一种只读存储器,但当明确给定 一个命令时就会变为可写的。所有形式的 ROM 都是固件,因为它的特性介于硬件和软件之间。通常,固件存在的问题是:执行代码比在 RAM 中慢。有些系统将操作系统保存在固件中,而在执行时将其复制到 RAM 中,以便执行更快。固件的最后一个问题是相对较贵,所以通常只有少量可用

对大型操作系统(包括大多数的通用操作系统,如 Windows、Mac OS X 和 UNIX) 或经常改变的系统,引导程序存放在固件上,而操作系统放在磁盘上。 在这种情况下,引导程序会先进行诊断,然后从磁盘固定位置(如第 0 块) 读取整块信息到内存,最后执行引导块的代码。存储在引导块 的程序可能足以加载整个操作系统到内存,并开始执行。更典型地,它只是简单的代码(因为它要存放在单一的磁盘块上),并且只知道磁盘的地址以及 引导程序其余部分的长度。GRUB 是一个开源的例子,用于引导 Linux 系统。所有磁盘的引导程序和操作系统本身,通过向磁盘写入新的版本,就可以很容易地改变。 具有引导分区的磁盘称为引导盘系统盘

整个引导程序在加载后,就可遍历文件系统以寻找操作系统内核,将其加载到内存中,并开始执行。只有到这时,才说系统是在运行