操作系统-简要笔记
操作系统原理
目录
- 操作系统原理
- 一级目录
- 二级目录
- 基本概念
- 处理器管理
- 存储管理
- 主要模式
- 功能
- 虚拟存储器
- 存储管理的硬件支撑
- 单连续分区存储管理
- 页式存储管理
- 段式存储管理
- 段页式存储管理
- 设备管理
- 基本概念
- I/O控制方式
- I/O软件
- I/O缓冲区
- 设备独立性
- 设备的分配方式
- 磁盘
- 虚拟设备
- 文件管理
- 并发程序设计
一级目录
二级目录
三级目录
基本概念
计算机硬件系统
组成
*处理器
*处理器是计算机的运算核心(Core)和控制单元( Control Unit) ,主要包括:
- 运算逻辑部件: 一个或多个运算器
- 寄存器部件: 包括通用寄存器、 控制与状态寄存器, 以及高速缓冲存储器(Cache)
- 控制部件: 实现各部件间联系的数据、 控制及状态的内部总线; 负责对指令译码、发出为完成每条指令所要执行操作的控制信号、 实现数据传输等功能的部件
处理器与寄存器
主存储器
DRAM
外围设备
设备类型
-
输入设备
键盘 鼠标
-
输出设备
显示器
-
存储设备
-
硬盘 如固态硬盘 机械硬盘 U盘等
-
光驱
····
-
-
网络通信设备
网卡等
设备控制方式
- 轮询方式: CPU忙式控制+数据交换
- 中断方式: CPU启动/中断+数据交换
- DMA方式: CPU启动/中断, DMA数据交换
总线
简介
总线(Bus) 是计算机各种功能部件之间传送信息的公共通信干线, 它是CPU、 内存、输入输出设备传递信息的公用通道
计算机的各个部件通过总线相连接, 外围设备通过相应的接口电路再与总线相连接, 从而形成了计算机硬件系统
按照所传输的信息种类, 总线包括一组控制线、 一组数据线和一组地址线
总线的类型
内部总线: 用于CPU芯片内部连接各元件
系统总线: 用于连接CPU、 存储器和各种I/O模块等主要部件
系统总线也有分级,如下面的图所示
通信总线: 用于计算机系统之间通信
冯诺依曼结构
存储程序计算机
冯·诺伊曼等人在1946年总结并明确提出,被称为冯·诺伊曼计算机模型存储程序计算机在体系结构上主要特点
- 以运算单元为中心, 控制流由指令流产生
- 采用存储程序原理, 面向主存组织数据流
- 主存是按地址访问、 线性编址的空间
- 指令由操作码和地址码组成
- 数据以二进制编码
结构
存储器的组织层次
存储器包括CPU中的高速缓存、主存储器、外围设备中的硬盘和网络中的远程存储器等
计算机软件系统
软件开发的不同层次
- 计算机硬件系统: 机器语言
- 操作系统之资源管理: 机器语言+广义指令(扩充了硬件资源管理)
- 操作系统之文件系统: 机器语言+系统调用(扩充了信息资源管理)
- 数据库管理系统: +数据库语言(扩充了功能更强的信息资源管理)
- 语言处理程序: 面向问题的语言
计算机程序的执行过程
操作系统
操作系统(Operating System), 简称OS
OS是计算机系统最基础的系统软件, 管理软硬件资源、 控制程序执行, 改善人机界面, 合理组织计算机工作流程, 为用户使用计算机提供良好运行环境
简而言之, 操作系统是方便用户、 管理和控制计算机软硬件资源的系统程序集合
- 从用户角度看, OS管理计算机系统的各种资源, 扩充硬件的功能, 控制程序的执行
- 从人机交互看, OS是用户与机器的接口,提供良好的人机界面, 方便用户使用计算机,在整个计算机系统中具有承上启下的地位
- 从系统结构看, OS是一个大型软件系统,其功能复杂, 体系庞大, 采用层次式、 模块化的程序结构
操作系统的组成
- 进程调度子系统
- 进程通信子系统
- 内存管理子系统
- 设备管理子系统
- 文件管理子系统
- 网络通信子系统
- 作业控制子系统
类型
操作控制方式
- 多道批处理操作系统, 脱机控制方式
- 分时操作系统, 交互式控制方式
- 实时操作系统
应用领域
- 服务器操作系统、 并行操作系统
- 网络操作系统、 分布式操作系统
- 个人机操作系统、 手机操作系统
- 嵌入式操作系统、 传感器操作系统
资源管理
计算机资源包含
- 硬件资源
处理器、 内存、 外设 - 信息资源
数据、 程序
屏蔽资源使用的底层细节
驱动程序: 最底层的、 直接控制和监视各类硬件(或文件)资源的部分
职责是隐藏底层硬件的具体细节, 并向其他部分提供一个抽象的、 通用的接口
比如说: 打印一段文字或一个文件, 既不需知道文件信息存储在硬盘上的细节,也不必知道具体打印机类型和控制细节
资源共享方式
- 独占使用方式
- 并发使用方式
资源分配策略
- 静态分配方式
- 动态分配方式
- 资源抢占方式
系统控制
CPU速度与I/O速度不匹配的矛盾非常突出.只有让多道程序同时进入内存争抢CPU运行, 才可以够使得CPU和外围设备充分并行, 从而提高计算机系统的使用效率
多道程序系统的实现
-
为进入内存执行的程序建立管理实体: 进程
-
OS应能管理与控制进程程序的执行
-
OS协调管理各类资源在进程间的使用
- 处理器的管理和调度
- 主存储器的管理和调度
- 其他资源的管理和调度
-
如何使用资源: 调用操作系统提供的服务例程(如何陷入操作系统)
-
如何复用CPU: 调度程序(在CPU空闲时让其他程序运行)
-
如何使CPU与I/O设备充分并行: 设备控制器与通道(专用的I/O处理器)
-
如何让正在运行的程序让出CPU: 中断(中断正在执行的程序, 引入OS处理)
控制方式
脱机作业控制方式
-
OS: 提供作业说明语言
-
用户: 编写作业说明书, 确定作业加工控制步骤,并与程序数据一并提交
-
操作员: 通过控制台输入作业
-
OS: 通过作业控制程序自动控制作业的执行
例: 批处理OS的作业控制方式, UNIX的shell程序,DOS的bat文件
联机作业控制方式
-
计算机: 提供终端(键盘/显示器)
-
用户: 登录系统
-
OS: 提供命令解释程序
-
用户: 联机输入命令, 直接控制作业步的执行
例: 分时OS的交互控制方式
命令解释程序
不管是脱机控制方式还是联机控制方式都需要命令解释程序
命令解释程序: 接受和执行一条用户提出的对作业的加工处理命令
当一个新的批作业被启动, 或新的交互型用户登录进系统时, 系统就自动地执行命令解释程序, 负责读入控制卡或命令行, 作出相应解释, 并予以执行
会话语言: 可编程的命令解释程序
处理过程
- OS启动命令解释程序, 输出命令提示符, 等待(键盘中断/鼠标点击/多通道识别)
- 每当用户输入一条命令(暂存在命令缓冲区)并按回车换行时, 申请中断
- CPU响应后, 将控制权交给命令解释程序,接着读入命令缓冲区内容, 分析命令、 接受参数, 执行处理代码
- 前台命令执行结束后, 再次输出命令提示符,等待下一条命令
- 后台命令处理启动后, 即可接收下条命令
前台命令:必须执行完毕后,才能继续输入命令
后台命令:命令启动后,可以继续启动下一个命令,而命令在后台的执行不影响
系统接口
操作系统的程序接口——系统调用
操作系统实现的完成某种特定功能的过程; 为所有运行程序提供访问操作系统的接口
就是操作系统为一些操作提供了接口,应用程序需要执行这些操作的时候就会去调用这些接口
实现
-
编写系统调用处理程序
操作系统会提前提供这些系统调用处理程序
-
设计一张系统调用入口地址表, 每个入口地址指向一个系统调用的处理程序, 并包含系统调用自带参数的个数
通过软件发起,系统查阅系统调用入口地址表,找到相应的系统调用处理程序
-
陷入处理机制需开辟现场保护区, 以保存发生系统调用时的处理器现场
在调用系统调用之前,将当前的处理器状况存储,以便调用后恢复处理器现场
系统结构
结构设计
OS构件
内核、 进程、 线程、 管程等
内核设计是OS设计中最为复杂的部分
设计概念
模块化、 层次式、 虚拟化
内核
单内核:内核中各部件杂然混居的形态, 始于1960年代, 广泛使用; 如Unix/Linux, 及Windows(自称采用混合内核的CS结构)
微内核:1980年代始, 强调结构性部件与功能性部件的分离, 大部分OS研究都集中在此
混合内核:微内核和单内核的折中, 较多组件在核心态中运行, 以获得更快的执行速度
外内核:尽可能减少内核的软件抽象化和传统微内核的消息传递机制,使得开发者专注于硬件的抽象化,部分嵌入式系统使用
处理器管理
处理器与寄存器
处理器部件
指令译码器ID:负责具体的解释指令的执行
指令暂存器IR:负责对指令的存储
程序计数器PC:指向下一跳要执行指令的地址
算术逻辑单元在完成计算之后会将内容汇总到标志寄存器Flag中
内存地址寄存器MAR、内存数据寄存器MDR:用于访问内存数据
用户程序可见寄存器
可以使程序员减少访问主存储器的次数, 提高指令执行的效率
所有程序可使用, 包括应用程序和系统程序
- 数据寄存器: 又称通用寄存器
- 地址寄存器: 索引、 栈指针、 段地址等寄存器
控制与状态寄存器
用于控制处理器的操作; 主要被具有特权的操作系统程序使用, 以控制程序的执行
- 程序计数器PC: 存储将取指令的地址
- 指令寄存器IR: 存储最近使用的指令
- 条件码CC: CPU为指令操作结果设置的位, 标志正/负/零/溢出等结果
- 标志位: 中断位、 中断允许位、 中断屏蔽位、 处理器模式位、 内存保护位、 …, 等
程序状态字PSW
PSW既是操作系统的概念, 指记录当前程序运行的动态信息, 通常包含:
- 程序计数器, 指令寄存器, 条件码
- 中断字, 中断允许/禁止, 中断屏蔽, 处理器模式, 内存保护、 调试控制
PSW也是计算机系统的寄存器
-
通常设置一组控制与状态寄存器
-
也可以专设一个PSW寄存器
指令与处理机
机器指令
机器指令是计算机系统执行的基本命令, 是*处理器执行的基本单位
指令由一个或多个字节组成, 包括操作码字段、 一个或多个操作数地址字段、 以及一些表征机器状态的状态字以及特征码
指令完成各种算术逻辑运算、 数据传输、 控制流跳转
指令执行过程
CPU根据PC(程序计数器)取出指令, 放入IR, 并对指令译码,然后发出各种控制命令, 执行微操作系列,从而完成一条指令的执行
一种指令执行步骤如下
- 取指: 根据PC从存储器或高速缓冲存储器中取指令到IR
- 解码: 解译IR中的指令来决定其执行行为
- 执行: 连接到CPU部件, 执行运算, 产生结果并写回, 同时在CC里设置运算结论标志; 跳转指令操作PC, 其他指令递增PC值
指令执行周期与指令流水线
特权指令与非特权指令
用户程序并非能够使用全部机器指令, 那些与计算机核心资源相关的特殊指令会被保护,核心资源相关的指令只能被操作系统程序使用
如: 启动I/O指令、 置PC指令、 等等
假设A程序要输出123,同时B程序要输出456,如果将I/O控制交给计算机很有可能输出成142536,不符合要求
所以指令被分为特权指令和非特权指令
- 特权指令: 只能被操作系统内核使用的指令
- 非特权指令: 能够被所有程序使用的指令
处理器模式
计算机通过设置处理器模式实现特权指令管理
计算机一般设置0、 1、 2、 3等四种运行模式,建议分别对应: 0操作系统内核、 1系统调用、2共享库程序、 3用户程序等保护级别
一般来说, 现代操作系统只使用0和3两种模式,对应于内核模式和用户模式
处理器模式的切换
包括“用户模式→内核模式”和“内核模式→用户模式” 的转换
中断、 异常或系统异常等事件导致用户程序向OS内核切换, 触发: 用户模式→内核模式
- 程序请求操作系统服务
- 程序运行时发生异常
- 程序运行时发生并响应中断
OS内核处理完成后, 调用中断返回指令(如Intel的iret) 触发: 内核模式→用户模式
中断
概念
中断是指程序执行过程中, 遇到急需处理的事件时, 暂时中止CPU上现行程序的运行,转去执行相应的事件处理程序, 待处理完成后再返回原程序被中断处或调度其他程序执行的过程
操作系统是“中断驱动” 的; 换言之, 中断是**操作系统的唯一方式
比如用户程序在运行的时候只有通过中断才能够切换
中断有广义和狭义之分, 上述中断是指广义的中断
中断、 异常与系统异常
-
狭义的中断指来源于处理器之外的中断事件,即与当前运行指令无关的中断事件, 如I/O中
断、 时钟中断、 外部信号中断等 -
异常指当前运行指令引起的中断事件, 如地址异常、 算术异常、 处理器硬件故障等
-
系统异常指执行陷入指令而触发系统调用引起的中断事件, 如请求设备、 请求I/O、 创建进程等
系统异常与硬件无关
中断源
处理器硬件故障中断事件
由处理器、 内存储器、 总线等硬件故障引起
处理原则为: 保护现场, 停止设备, 停止CPU, 向操作员报告, 等待人工干预
程序性中断事件
处理器执行机器指令引起
- 除数为零、 操作数溢出等算术异常: 简单处理, 报告用户; 也可以由用户编写中断续元程序处理
- 非法指令、 用户态使用特权指令、 地址越界、 非法存取等指令异常: 终止进程
- 终止进程指令: 终止进程
- 虚拟地址异常: 调整内存后重新执行指令
自愿性中断事件
处理器执行陷入指令请求OS服务引起; 在操作系统中, 它一般又被称作系统调用
- 请求分配外设、 请求I/O、 等等
- 处理流程是: 陷入OS, 保护现场, 根据功能号查入口地址, 跳转具体处理程序
I/O中断事件
来源于外围设备报告I/O状态的中断事件
- I/O完成: 调整进程状态, 释放等待进程
- I/O出错: 等待人工干预
- I/O异常: 等待人工干预
外部中断事件
由外围设备发出的信号引起的中断事件
- 时钟中断、 间隔时钟中断: 记时与时间片处理
- 设备报到与结束中断: 调整设备表
- 键盘/鼠标信号中断: 根据信号作出相应反应
- 关机/重启动中断: 写回文件, 停止设备与CPU
中断系统
中断系统是计算机系统中响应和处理中断的系统, 包括硬件子系统和软件子系统两部分
中断响应由硬件子系统完成
中断处理由软件子系统完成
中断响应处理与指令执行周期
在指令执行周期最后增加一个微操作, 以响应中断
中断装置
计算机系统中发现并响应中断/异常的硬件装置称为中断装置。由于中断源的多样性, 硬件实现的中断装置有多种, 分别处理不同类型的中断这些中断装置因计算机而异, 通常有:
- 处理器外的中断: 由中断控制器发现和响应
- 处理器内的异常: 由指令的控制逻辑和实现线路发现和响应, 相应机制称为陷阱
- 请求OS服务的系统异常: 处理器执行陷入指令时直接触发, 相应机制称为系统陷阱
中断控制器
CPU中的一个控制部件, 包括中断控制逻辑线路和中断寄存器
- 外部设备向其发出中断请求IRQ, 在中断寄存器中设置已发生的中断
- 指令处理结束前, 会检查中断寄存器, 若有不被屏蔽的中断产生, 则改变处理器内操作的顺序, 引出操作系统中的中断处理程序
这个过程是异步的,先设置寄存器,在这条指令结束之后查看寄存器,才能进行中断
陷阱与系统陷阱
陷阱与系统陷阱: 指令的逻辑和实现线路的一部分
- 执行指令出现异常后, 会根据异常情况转向操作系统的异常处理程序
- 出现虚拟地址异常后, 需要重新执行指令,往往越过陷阱独立设置页面异常处理程序
- 执行陷入指令后, 越过陷阱处理, 触发系统陷阱, **系统调用处理程序
这个过程是同步的,是在执行指令的过程中发生的中断
中断响应过程
-
发现中断源, 提出中断请求
-
发现中断寄存器中记录的中断
-
决定这些中断是否应该屏蔽
-
当有多个要响应的中断源时, 根据规定的优先级选择一个
-
-
中断当前程序的执行
保存当前程序的PSW/PC到核心栈
-
转向操作系统的中断处理程序
中断处理程序
操作系统处理中断事件的控制程序, 主要任务是处理中断事 件和恢复正常操作
中断处理过程
-
保护未被硬件保护的处理器状态
-
通过分析被中断进程的PSW中断码字段,识别中断源
-
分别处理发生的中断事件
-
恢复正常操作
情况一: 对于某些中断, 在处理完毕后, 直接返回刚刚被中断的进程
情况二: 对于其他一些中断, 需要中断当前进程的运行, 调整进程队列, 启动进程调度, 选择下一个执行的进程并恢复其执行
多中断的响应与处理
中断屏蔽
当计算机检测到中断时, 中断装置通过中断屏蔽位决定是否响应已发生的中断,有选择的响应中断
中断优先级
当计算机同时检测到多个中断时, 中断装置响应中断的顺序,有优先度的响应中断
一种可能的处理次序:
- 处理机硬件故障中断事件
- 自愿性中断事件
- 程序性中断事件
- 时钟中断等外部中断事件
- 输入输出中断事件
- 重启动和关机中断事件
不同类型的操作系统有不同的中断优先级
中断的嵌套处理
当计算机响应中断后, 在中断处理过程中,可以再响应其他中断
操作系统是性能攸关程序系统, 且中断响应处理有硬件要求, 考虑系统效率和实现代价问题, 中断的嵌套处理应限制在一定层数内,如3层
中断的嵌套处理了改变中断处理次序, 导致先响应的有可能后处理
进程
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,也是操作系统进行资源分配和调度的一个独立单位
一个进程包括五个实体部分
- (OS管理运行程序的)数据结构P
- (运行程序的)内存代码C
- (运行程序的)内存数据D
- (运行程序的)通用寄存器信息R
- (OS控制程序执行的)程序状态字信息PSW
不同程序
-
在不同数据集上运行: 构成两个无关进程
-
在相同数据集上运行: 构成两个共享数据的交往进程
相同程序
- 在不同数据集上运行: 构成两个共享代码的无关进程
进程状态
-
运行态:进程占有处理器运行
-
就绪态:进程具备运行条件等待处理器运行
-
等待态:进程由于等待资源、 输入输出、 信号等而不具备运行条件
-
运行态→ 等待态:等待资源、 I/O、 信号
-
等待态→ 就绪态:资源满足、 I/O结束、信号完成
-
运行态→ 就绪态:运行时间片到、有更高优先权进程
-
就绪态→ 运行态:处理器空闲时选择更高优先权进程抢占
进程挂起
OS无法预期进程的数目与资源需求, 计算机系统在运行过程中可能出现资源不足的情况
运行资源不足表现为性能低和死锁两种情况
解决办法: 剥夺某些进程的内存及其他资源,调入OS管理的对换区, 不参加进程调度, 待适当时候再调入内存、恢复资源、参与运行,这就是进程挂起
挂起态与等待态有着本质区别, 后者占有已申请到的资源处于等待, 前者没有任何资源
进程挂起的选择与恢复
- 一般选择等待态进程进入挂起等待态
- 也可选择就绪态进程进入挂起就绪态
- 运行态进程还可以挂起自己
- 等待事件结束后,挂起等待态进入挂起就绪态
- 一般选择挂起就绪态进程予以恢复
数据描述
进程控制块
进程控制块PCB是OS用于记录和刻画进程状态及环境信息的数据结构
分为标识信息、现场信息、控制信息
标识信息
用于存放唯一标识该进程的信息
- 系统分配的标识号
- 系统分配的进程组标识号
- 用户定义的进程名
- 用户定义的进程组名
现场信息
用于存放该进程运行时的处理器现场信息
- 用户可见寄存器内容: 数据寄存器、 地址寄存器
- 控制与状态寄存器内容: PC、 IR、 PSW
- 栈指针内容: 核心栈与用户栈指针
控制信息
用于存放与管理、 调度进程相关的信息
- 调度相关信息: 状态、 等待事件/原因、 优先级
- 进程组成信息: 代码/数据地址、 外存映像地址
- 队列指引元: 进程队列指针、 父子兄弟进程指针
- 通信相关信息: 消息队列、 信号量、 锁
- 进程特权信息: 如内存访问权限、 处理器特权
- 处理器使用信息: 占用的处理器、 时间片、 处理器使用时间/已执行总时间、 记账信息
- 资源清单信息: 如正占有的资源、 已使用的资源
进程映像
某一时刻进程的内容及其执行状态集合,是内存级的物理实体, 又称为进程的内存映像,包含:
- 进程控制块: 保存进程的标识信息、 状态信息和控制信息
- 进程程序块: 进程执行的程序空间
- 进程数据块: 进程处理的数据空间, 包括数据、 处理函数的用户栈和可修改的程序
- 核心栈: 进程在内核模式下运行时使用的堆栈, 中断或系统过程使用
进程上下文
进程的执行需要环境支持, 包括CPU现场和Cache中的执行信息,OS中的进程物理实体和支持进程运行的环境合成进程上下文, 包括以下:
- 用户级上下文: 用户程序块/用户数据区/用户栈/用户共享内存
- 寄存器上下文: PSW/栈指针/通用寄存器
- 系统级上下文: PCB/内存区表/核心栈
进程上下文刻画了进程的执行情况
进程的管理
关键的进程管理软件包括:
- 系统调用/中断/异常处理程序
- 队列管理模块
- 进程控制程序
- 进程调度程序(独立进程居多)
- 进程通信程序(多个程序包)
- 终端登录与作业控制程序、 性能监控程序、 审计程序等外围程序
队列管理模块
操作系统建立多个进程队列, 包括就绪队列和等待队列,按需组织为先进先出队列与优先队列。队列中的进程可以通过PCB中的队列指引元采用单/双指引元或索引连接。进程与资源调度围绕进程队列展开。
控制与管理
- 进程创建: 进程表加一项, 申请PCB并初始化,生成标识, 建立映像, 分配资源, 移入就绪队列
- 进程撤销: 从队列中移除, 归还资源, 撤销标识,回收PCB, 移除进程表项
- 进程阻塞: 保存现场信息, 修改PCB, 移入等待队列, 调度其他进程执行
- 进程唤醒: 等待队列中移出, 修改PCB, 移入就绪队列(该进程优先级高于运行进程触发抢占)
- 进程挂起: 修改状态并出入相关队列, 收回内存等资源送至对换区
- 进程**: 分配内存, 修改状态并出入相关队列
- 其他: 如修改进程特权
原语与进程控制原语
进程控制过程中涉及对OS核心数据结构(进程表/PCB池/队列/资源表)的修改,为防止与时间有关的错误, 应使用原语
原语是由若干条指令构成的完成某种特定功能的程序,执行上具有不可分割性。原语的执行可以通过关中断实现
进程控制使用的原语称为进程控制原语,另一类常用原语是进程通信原语
进程切换
进程切换指从正在运行的进程中收回处理器,让待运行进程来占有处理器运行 ,进程切换实质上就是被中断运行进程与待运行进程的上下文切换, 处理过程是:
- 保存被中断进程的上下文
- 转向进程调度
- 恢复待运行进程的上下文
进程的切换必须在操作系统内核模式下完成,也就必须需要模式切换
模式切换
模式切换又称处理器状态切换, 包括:
-
用户模式到内核模式
由中断/异常/系统调用中断用户进程执行而触发- 处理器模式转为内核模式
- 保存当前进程的PC/PSW值到核心栈
- 转向中断/异常/系统调用处理程序
-
内核模式到用户模式
OS执行中断返回指令将控制权交还用户进程而触发- 从待运行进程核心栈中弹出PSW/PC值
- 处理器模式转为用户模式
进程切换工作过程
- (中断/异常等触发)正向模式切换并压入PSW/PC
- 保存被中断进程的现场信息
- 处理具体中断/异常
- 把被中断进程的系统堆栈指针SP值保存到PCB
- 调整被中断进程的PCB信息, 如进程状态
- 把被中断进程的PCB加入相关队列
- 选择下一个占用CPU运行的进程
- 修改被选中进程的PCB信息, 如进程状态
- 设置被选中进程的地址空间, 恢复存储管理信息
- 恢复被选中进程的SP值到处理器寄存器SP
- 恢复被选中进程的现场信息进入处理器
- (中断返回指令触发)逆向模式转换并弹出PSW/PC
进程切换的发生时机
进程切换一定发生在中断/异常/系统调用,处理过程中, 常见的情况是:
- 阻塞式系统调用、 虚拟地址异常导致被中断进程进入等待态
- 时间片中断、 I/O中断后发现更高优先级进程,导致被中断进程转入就绪态
- 终止用系统调用、 不能继续执行的异常,导致被中断进程进入终止态
一些中断/异常不会引起进程状态转换, 不会引起进程切换, 只是在处理完成后把控制权交回给被中断进程, 处理流程是:
- (中断/异常触发)正向模式切换压入PSW/PC
- 保存被中断进程的现场信息
- 处理中断/异常
- 恢复被中断进程的现场信息
- (中断返回指令触发)逆向模式转换弹出PSW/PC
多线程技术
传统进程是单线程结构进程
单线程结构进程在并发程序设计上存在的问题 :
- 进程切换开销大
- 进程通信开销大
- 限制了进程并发的粒度
- 降低了并行计算的效率
操作系统会根据安全角度对进程之间的通信做一些限制,且进程之间的调度需要耗费的成本更高
多线程结构进程
线程是进程的一条执行路径, 是调度的基本单位, 同一个进程中的所有线程共享进程获得的主存空间和资源
线程状态有运行、 就绪和睡眠, 无挂起
挂起与是否占有资源有关,而线程使用的是进程的资源
OS感知线程环境下:
- 处理器调度对象是线程
- 进程没有三状态(或者说只有挂起状态)
OS不感知线程环境:
-
处理器调度对象仍是进程
-
用户空间中的用户调度程序调度线程
优点
- 快速线程切换
- 减少(系统) 管理开销
- (线程) 通信易于实现
- 并行程度提高
- 节省内存空间
多线程的实现
内核级线程KLT, Kernel-Level Threads
线程管理的所有工作由OS内核来做
特点
- 进程中的一个线程被阻塞了, 内核能调度同一进程的其它线程占有处理器运行
- 多处理器环境中, 内核能同时调度同一进程中多个线程并行执行
- 内核自身也可用多线程技术实现, 能提高操作系统的执行速度和效率
- 应用程序线程在用户态运行, 线程调度和管理在内核实现, 在同一进程中, 控制权从一个线程传送到另一个线程时需要模式切换,系统开销较大
用户级线程ULT, User-Level Threads
用户空间运行的线程库,提供多线程应用程序的开发和运行支撑环境。
线程管理的所有工作都由应用程序完成,内核没有意识到线程的存在。
特点
- 所有线程管理数据结构均在进程的用户空间中, 线程切换不需要内核模式, 能节省模式切换开销和内核的宝贵资源
- 允许进程按应用特定需要选择调度算法, 甚至根据应用需求裁剪调度算法
- 能运行在任何OS上, 内核在支持ULT方面不需要做任何工作
- 不能利用多处理器的优点, OS调度进程,仅有一个ULT能执行
- 一个ULT的阻塞, 将引起整个进程的阻塞
Jacketing技术
把阻塞式系统调用改造成非阻塞式的,当线程陷入系统调用时,执行jacketing程序。由jacketing 程序来检查资源使用情况,以决定是否执行进程切换或传递控制权给另一个线程。
混合式多线程
单应用的多个ULT可以映射成一些KLT, 通过调整KLT数目,可以达到较好的并行效果
线程混合式策略下的线程状态
- 活跃态ULT代表绑定KLT的三态
- 活跃态ULT运行时可**用户调度
- 非阻塞系统调用可使用Jacketing启动用户调度, 调整活跃态ULT
处理器调度
调度的层次
高级调度
又称长程调度, 作业调度决定能否加入到执行的进程池中
分时OS中, 高级调度决定:
- 是否接受一个终端用户的连接
- 命令能否被系统接纳并构成进程
- 新建态进程是否加入就绪进程队列
中级调度
又称平衡负载调度,决定主存中的可用进程集合
- 引进中级调度是为了提高内存利用率和作业吞吐量
- 中级调度决定那些进程被允许驻留在主存中参与竞争处理器及其他资源, 起到短期调整系统负荷的作用
- 中级调度把一些进程换出主存, 从而使之进入“挂起” 状态, 不参与进程调度,以平顺系统的负载
低级调度
又称短程调度, 进程调度决定哪个可用进程占用处理器执行
- 进程调度程序: 又称分派程序, 操作系统中实现处理器调度的程序, 是操作系统的最核心部分
- 处理器调度策略的优劣直接影响到整个系统的性能
主要功能
- 记住进程或内核级线程的状态
- 决定某个进程或内核级线程什么时候获得处理器, 以及占用多长时间
- 把处理器分配给进程或内核级线程
- 收回处理器
调度算法
选择处理器调度算法的原则
- 资源利用率: 使得CPU或其他资源的使用率尽可能高且能够并行工作
- 响应时间: 使交互式用户的响应时间尽可能小, 或尽快处理实时任务
- 周转时间: 提交给系统开始到执行完成获得结果为止的这段时间间隔称周转时间, 应该使周转时间或平均周转时间尽可能短
- 吞吐量: 单位时间处理的进程数尽可能多
- 公平性: 确保每个用户每个进程获得合理的CPU份额或其他资源份额
优先数调度算法
根据分配给进程的优先数决定运行进程
分类
- 抢占式优先数调度算法
- 非抢占式优先数调度算法
与进入系统时间相关的优先数
-
计算时间短(作业/进程)优先
-
剩余计算时间短进程优先
-
响应比高者(作业/进程)优先
-
先来先服务: 先进队先被选择
-
多用于高级调度; 低级调度中, 以计算为主的进程过于优越
时间片轮转调度算法
- 根据各个进程进入就绪队列的时间先后轮流占有CPU一个时间片
- 时间片中断
- 时间片的确定: 选择长短合适的时间片, 过长则退化为先来先服务算法, 过短则调度开销大
- 不同进程时间片长度可调
分级调度算法
又称多队列策略, 反馈循环队列
基本思想
- 建立多个不同优先级的就绪进程队列
- 多个就绪进程队列间按照优先数调度
- 高优先级就绪进程, 分配的时间片短
- 单个就绪进程队列中进程的优先数和时间片相同
例子:
**调度算法
基本思想
为进程发放针对系统各种资源(如CPU时间) 的**; 当调度程序需要做出决策时, 随机选择一张**,持有该**的进程将获得系统资源
合作进程之间可以进行**交换
存储管理
主要模式
逻辑地址
又称相对地址, 即用户编程所使用的地址空间
逻辑地址从0开始编号, 有两种形式:
- 一维逻辑地址(地址)
- 二维逻辑地址(段号:段内地址)
段式程序设计
- 把一个程序设计成多个段(代码段、数据段、堆栈段、等等)
- 用户可以自己应用段覆盖技术扩充内存空间使用量
物理地址
又称绝对地址, 即程序执行所使用的地址空间,处理器执行指令时按照物理地址进行
主存储器的复用
按照分区复用
- 主存划分为多个固定/可变尺寸的分区
- 一个程序/程序段占用一个分区
按照页架复用
-
主存划分成多个固定大小的页架
-
一个程序/程序段占用多个页架
存储管理的基本模式
将逻辑地址和物理地址相对于,就会有2*2=4个存储管理的基本模式
- 单连续存储管理: 一维逻辑地址空间的程序占用一个主存固定分区或可变分区
- 段式存储管理: 段式二维逻辑地址空间的程序占用多个主存可变分区
- 页式存储管理: 一维逻辑地址空间的程序占用多个主存页架区
- 段页式存储管理: 段式二维逻辑地址空间的程序占用多个主存页架区
功能
地址转换
又称重定位, 即把逻辑地址转换成绝对地址
静态重定位
在程序装入内存时进行地址转换
由装入程序执行, 早期小型OS使用
动态重地位
在CPU执行程序时进行地址转换
从效率出发, 依赖硬件地址转换机构
分配与去配
分配
进程装入主存时, 存储管理软件进行具体的主存分配操作, 并设置一个表格记录主存空间的分配情况
去配
当某个进程撤离或主动归还主存资源时, 存储管理软件要收回它所占用的全部或者部分存储空间, 调整主存分配表信息
空间共享
多个进程共享主存储器资源: 多道程序设计技术使若干个程序同时进入主存储器, 各自占用一定数量的存储空间, 共同使用一个主存储器
多个进程共享主存储器的某些区域: 若干个协作进程有共同的主存程序块或者主存数据块
存储保护
为避免主存中的多个进程相互干扰, 必须对主存中的程序和数据进行保护
- 私有主存区中的信息: 可读可写
- 公共区中的共享信息: 根据授权
- 非本进程信息: 不可读写
这一功能需要软硬件协同完成,CPU检查是否允许访问, 不允许则产生地址保护异常, 由OS进行相应处理。
空间的扩充
存储扩充: 把磁盘作为主存扩充, 只把部分进程或进程的部分内容装入内存
- 对换技术: 把部分不运行的进程调出
- 虚拟技术: 只调入进程的部分内容
这一工作需要软硬件协作完成
-
对换进程决定对换, 硬件机构调入
-
CPU处理到不在主存的地址, 发出虚拟地址异常, OS将其调入, 重执指令
虚拟存储器
提出
- 主存容量限制带来诸多不便
- 用户编写程序必须考虑主存容量限制
- 多道程序设计的道数受到限制
- 用户编程行为分析
- 全面考虑各种情况, 执行时有互斥性
- 顺序性和循环性等空间局部性行为
- 某一阶段执行的时间局部性行为
因此可以考虑部分调入进程内容
基本思想
- 存储管理把进程全部信息放在辅存中, 执行时先将其中一部分装入主存, 以后根据执行行为随用随调入
- 如主存中没有足够的空闲空间, 存储管理需要根据执行行为把主存中暂时不用的信息调出到辅存上去
实现思路
需要建立与自动管理两个地址空间
- (辅存)虚拟地址空间: 容纳进程装入
- (主存)实际地址空间: 承载进程执行
对于用户, 计算机系统具有一个容量大得多的主存空间, 即虚拟存储器。虚拟存储器是一种地址空间扩展技术,通常意义上对用户编程是透明的
存储管理的硬件支撑
存储管理涉及的存储对象
- 为获得更好的处理性能, 部分主存程序与数据(特别是关键性能数据) 被调入Cache, 存储管理需要对其进行管理, 甚至包括对联想存储器的管理
- 为获得更大的虚拟地址空间, 存储管理需要对存放在硬盘、 固态硬盘、 甚至网络硬盘上的虚拟存储器文件进行管理
高速缓存存储器(Cache)
- Cache是介于CPU和主存储器间的高速小容量存储器, 由静态存储芯片SRAM组成, 容量较小但比主存DRAM技术更加昂贵而快速, 接近于CPU的速度
- CPU往往需要重复读取同样的数据块,Cache的引入与缓存容量的增大, 可以大幅提升CPU内部读取数据的命中率,从而提高系统性能
高速缓存存储器的构成
- 高速缓冲存储器通常由高速存储器、 联想存储器、 地址转换部件、 替换逻辑等组成
- 联想存储器: 根据内容进行寻址的存储器
- 地址转换部件: 通过联想存储器建立目录表以实现快速地址转换。 命中时直接访问Cache; 未命中时从内存读取放入Cache
- 替换部件: 在缓存已满时按一定策略进行数据块替换, 并修改地址转换部件
高速缓存存储器的组织
- 由于CPU芯片面积和成本, Cache很小
- 根据成本控制, 划分为L1、 L2、 L3三级
L1 Cache: 分为数据缓存和指令缓存;内置; 其成本最高, 对CPU的性能影响最大; 通常在32KB-256KB之间
L2 Cache: 分内置和外置两种, 后者性能低一些; 通常在512KB-8MB之间
L3 Cache: 多为外置, 在游戏和服务器领域有效; 但对很多应用来说, 总线改善比设置L3更加有利于提升系统性能
单连续分区存储管理
每个进程占用一个物理上完全连续的存储空间(区域)
单用户连续存储管理
-
主存区域划分为系统区与用户区,设置一个栅栏寄存器界分两个区域, 硬
件用它在执行时进行存储保护 -
一般采用静态重定位进行地址转换,硬件实现代价低
静态重定位: 在装入一个作业时, 把该作业中程序的指令地址和数据地址全部转换成绝对地址
-
适用于单用户单任务操作系统, 如DOS
固定分区存储管理
- 支持多个分区
- 分区数量固定、大小固定
- 可用静态重定位
- 硬件实现代价低
- 早期OS采用
主存分配
主存分配表
地址转换
可变分区存储管理
按进程的内存需求来动态划分分区
创建一个进程时, 根据进程所需主存量查看主存中是否有足够的空闲空间
- 若有, 则按需要量分割一个分区
- 若无, 则令该进程等待主存资源
由于分区大小按照进程实际需要量来确定, 因此分区个数是随机变化的
已分配区表与未分配区表, 采用链表
内存分配
- 最先适应分配算法
- 邻近适应分配算法
- 最优适应分配算法
- 最坏适应分配算法
动态重定位
内存零头
- 固定分区方式会产生内存内零头
- 可变分区方式也会随着进程的内存分配产生一些小的不可用的内存分区, 称为内存外零头
- 最优适配算法最容易产生外零头
- 任何适配算法都不能避免产生外零头
移动技术(程序浮动技术)
移动分区以解决内存外零头,需要动态重定位支撑
页式存储管理
- 分页存储器将主存划分成多个大小相等的页架
- 受页架尺寸限制, 程序的逻辑地址也自然分成页
- 不同的页可以放在不同页架中, 不需要连续
- 页表用于维系进程的主存完整性
页式存储管理中的地址
逻辑地址
页式存储管理的逻辑地址由两部分组成,页号和单元号, 逻辑地址形式:
物理地址
页式存储管理的物理地址也有两部分组成,页架号和单元号, 物理地址形式:
地址转换
代价
可变分区存储的基准地址是存储在寄存器中的,速度很快,而页表放在主存,每次地址转换必须访问两次主存
- 按页号读出页表中的相应页架号
- 按计算出来的绝对地址进行读写
存在问题: 降低了存取速度
解决办法: 利用Cache存放部分页表
快表
为提高地址转换速度, 设置一个专用的高速存储器, 用来存放页表的一部分,存放在高速存储器中的页表部分就是快表
快表表项: 页号, 页架号
这种高速存储器是联想存储器, 即按照内容寻址, 而非按照地址访问
因为要找的是页号对应的页架号,知道页号,不知道地址,所以是内容寻址
eg:假定主存访问时间为200毫微秒, 快表访问时间为40毫微秒, 查快表的命中率是90%
平均地址转换代价为 $(200+40)*90%+(200+200)*10% =256毫微秒 $
比两次访问主存的时间(400毫微秒)下降了36%
地址转换流程
按逻辑地址中的页号查快表
- 若该页已在快表中, 则由页架号和单元号形成绝对地址
- 若该页不在快表中, 则再查主存页表形成绝对地址, 同时将该页登记到快表中
- 当快表填满后, 又要登记新页时, 则需在快表中按一定策略淘汰一个旧登记项
多道程序环境下的进程表
进程表中登记了每个进程的页表。进程占有处理器运行时, 其页表起始地址和长度送入页表控制寄存器
用户作业名 | 页表始址 | 页表长度 |
---|---|---|
AB | 0010 | 4 |
CD | 0014 | 3 |
EF | 0017 | 7 |
… | … | … |
多道程序环境下的地址转换
内存分配/去配
可用一张位示图来记录主存分配情况,建立进程页表维护主存逻辑完整性
对于每个页使用1位去记录该页是否被占用
页的共享
页式存储管理能够实现多个进程共享程序和数据
-
数据共享: 不同进程可以使用不同页号共享数据页
-
程序共享: 不同进程必须使用相同页号共享代码页
同一个程序不同的进程代码的位置是确定的
页式虚拟存储管理
把进程全部页面装入虚拟存储器, 执行时先把部分页面装入实际内存, 然后, 根据执行行为, 动态调入不在主存的页, 同时进行必要的页面调出
首次只把进程第一页信息装入主存, 称为请求页式存储管理
页式虚拟存储管理的页表
需要扩充页表项:
- 每页的虚拟地址、 实际地址
- 主存驻留标志、 写回标志、 保护标志、 引用标志、可移动标志
页式虚拟存储管理的实现
CPU处理地址
- 若页驻留, 则获得块号形成绝对地址
- 若页不在内存, 则CPU发出缺页中断
OS处理缺页中断
- 若有空闲页架, 则根据辅存地址调入页, 更新页表与快表等
- 若无空闲页架, 则决定淘汰页, 调出已修改页, 调入页, 更新页表与快表
页面调度
当主存空间已满而又需要装入新页时,页式虚拟存储管理必须按照一定的算法把已在主存的一些页调出去。选择淘汰页的工作称为页面调度。选择淘汰页的算法称为页面调度算法。
页面调度算法设计不当, 会出现(刚被淘汰的页面立即又要调入, 并如此反复),这种现象称为抖动或颠簸。
缺页中断率
假定进程P共n页, 系统分配页架数m个。P运行中成功访问次数为S, 不成功访问次数为F, 总访问次数A=S+F。缺页中断率定义为: f=F/A
影响缺页中断率的因素
- 分配给进程的页架数: 可用页架数越多, 则缺页中断率就越低
- 页面的大小: 页面尺寸越大, 则缺页中断率就越低
- 用户的程序编制方法: 在大数据量情况下, 对缺页中断率也有很大影响
eg:程序将数组置为“0”, 假定仅分得一个主存页架, 页面尺寸为128个字, 数组元素按行存放, 开始时第一页在主存
程序1:
int A[128][128]; for(int j=0;j<128;j++) for(int i=0;i<128;i++) A[i][j]=0;
内循环按照行进行遍历,导致每执行一次赋值就要产生一次缺页中断, 共产生(128×128- 1)次缺页中断
程序2:
int A[128][128]; for(int i=0;i<128;i++) for(int j=0;j<128;j++) A[i][j]=0;
内循环按照列进行遍历,共产生(128- 1)次缺页中断
OPT页面调度算法
理想的调度算法是: 当要调入新页面时, 首先淘汰以后不再访问的页, 然后选择距现在最长时间后再访问的页。该算法由Belady提出, 称Belady算法, 又称最佳算法(OPT)
OPT只可模拟, 不可实现
先进先出FIFO页面调度算法
总是淘汰最先调入主存的那一页, 或者说主存驻留时间最长的那一页(常驻的除外)
模拟的是程序执行的顺序性, 有一定合理性
最久未使用LRU页面调度算法
淘汰最近一段时间较久未被访问的那一页, 即那些刚被使用过的页面, 可能马上还要被使用到
模拟了程序执行的局部属性, 既考虑了循环性又兼顾了顺序性
严格实现的代价大(需要维持特殊队列)
LRU算法的模拟实现
每页建一个引用标志, 供硬件使用
设置一个时间间隔中断: 中断时页引用标志置0
地址转换时, 页引用标志置1
淘汰页面时, 从页引用标志为0的页中间随机选择
时间间隔多长是个难点
最不常用LFU页面调度算法
淘汰最近一段时间内访问次数较少的页面, 对OPT的模拟性比LRU更好
基于时间间隔中断, 并给每一页设置一个计数器,时间间隔中断发生后, 所有计数器清0每访问页1次就给计数器加1选择计数值最小的页面淘汰
时钟CLOCK页面调度算法
-
采用循环队列机制构造页面队列, 形成了一个类似于钟表面的环形表
-
队列指针则相当于钟表面上的表针, 指向可能要淘汰的页面
-
使用页引用标志位
工作流程
- 页面调入主存时, 其引用标志位置1
- 访问主存页面时, 其引用标志位置1
- 淘汰页面时, 从指针当前指向的页面开始扫描循环队列
- 把所遇到的引用标志位是1的页面的引用标志位清0, 并跳过
- 把所遇到的引用标志位是0的页面淘汰, 指针推进一步
反置页表
内存管理单元MMU:CPU管理虚拟/物理存储器的控制线路, 把虚拟地址映射为物理地址, 并提供存储保护, 必要时确定淘汰页面,是为页式存储管理设置的专门硬件机构。
反置页表IPT:MMU用的数据结构
为什么需要反置页表
在分页系统中,每个进程都有一个页表。现代系统中可能存在大量进程,每个进程都允许很大的逻辑地址空间,因而进程可能拥有一个很大的页表,这些页表会占用大量的内存空间。而通过物理页向逻辑页映射就可以节省很大的存储空间。
反置页表如何实现
内存中的每一个物理页设置一个表项,表项中存放进程号和页号,最后系统只维护一张反置页表。
反置页表的页表项
进程号 页号 标志位 链指针
进程号:使用该物理页的进程号
页号: 该物理页对应的虚拟地址页号
标志位: 有效、 引用、 修改、 保护和锁定等标志信息
链指针: 哈希链(哈希冲突的时候,通过链表串在一起)
反置页表的哈希表
如果是使用页表就可以直接从该进程的页表查询到页架号,而现在采用的是反置页表,在页表到页架号的映射上需要采用哈希查询,所以要维系一个哈希表。
哈希函数输入:进程号和页号
哈希函数输出:反置页表项的指针
地址转换过程
- 通过哈希表查询到反置页表项的指针
- 比对指向的页表项的进程号和页号
- 相同,则该页就是所需要的物理页
- 不相同,沿着链指针继续
- 如果有相同的,该页就是所需要的物理页
- 没有相同的,说明页面不在内存中,而在虚拟内存中,需要页面置换
段式存储管理
段式存储是面向开发人员的,开发人员根据自己的需要对程序进行划分,程序的不同的部分采用不同的段进行地址管理,而对内存的物理管理是基于可变分区存储管理的,只不过可变分区存储管理是一个进程一个段,而段式存储管理是一个进程多个段。
它与页式管理也不同,也是管理对于开发人员是透明的,系统自动对软件的内存按照也进行切割。而且页式管理每个页是大小相等,均匀分布的。而段式管理段的大小和位置是不确定的。
段式程序设计
每个程序可由若干段组成, 每一段都可以从“0”开始编址, 段内的地址是连续的
分段存储器的逻辑地址由两部分组成 段号单元号
段式存储管理的基本思想
段式存储管理基于可变分区存储管理实现, 一个进程要占用多个分区
硬件需要增加一组用户可见的段地址寄存器(代码段、 数据段、 堆栈段, 附加段) , 供地址转换使用
存储管理需要增加设置一个段表, 每个段占用一个段表项, 包括: 段始址、 段限长, 以及存储保护、 可移动、 可扩充等标志位
段的共享
通过不同进程段表中的项指向同一个段基址来实现
对共享段的信息必须进行保护, 如规定只能读出不能写入, 不满足保护条件则产生保护中断
段页式存储管理
段式存储管理可以基于页式存储管理实现
对于每一段进行页式管理
段页式存储管理的地址转换
设备管理
基本概念
I/O设备
现代计算机系统通常配备大量的I/O设备,用于计算机系统与外部世界(如用户、其它计算机或电子设备等)进行信息交换或存储
按设备管理划分
- 字符设备:以字符为单位进行信息交换,发送或接收一个字符流
- 人机交互设备大多是字符设备,例如鼠标、显示器等
- 块设备:以固定大小的数据块(块是存储介质上连续信息组成的一个区域)进行信息交换
- 存储设备通常为块设备,例如磁盘驱动器等
- 网络设备:用于与远程设备通信的设备
- 机机通信设备为网络设备,例如网卡等
- 网络设备可以抽象为传送字符流的特殊字符设备,也可以抽象为传送连续小块数据的块设备
设备管理的目标
-
克服设备和CPU速度的不匹配所引起的问题,使主机和设备并行工作,提高设备使用效率
-
对设备进行抽象,屏蔽设备的物理细节和操作过程,配置驱动程序,提供统一界面,供用户或高层软件使用
-
抽象为文件系统中的节点,统一管理
对设备的输入输出抽象为对文件的读和写
-
裸设备:不被操作系统直接管理,由应用程序读写,I/O效率更高
-
设备管理的功能
- 设备中断处理
- 缓冲区管理
- 设备的分配和去配
- 设备驱动调度
- 实现虚拟设备
设备管理的层次
- I/O硬件
- I/O设备及其接口线路
- 控制部件
- 通道
- I/O软件
- 系统I/O软件
- 用户空间I/O软件
I/O控制方式
设备管理器
设备控制器是计算机中的一个实体,其主要职责是控制一个或多个I/O设备,以实现I/O设备和计算机之间的数据交换。它是CPU与I/O设备之间的接口,它接收从CPU发来的命令,并去控制I/O设备工作,以使处理机从繁杂的设备控制事务中解脱出来。设备控制器是一个可编址的设备,当它仅控制一个设备时,它只有一个唯一的设备地址;若控制可连接多个设备时,则应含有多个设备地址,并使每一个设备地址对应一个设备。
数据交换是指CPU与控制器之间、控制器与设备之间的数据交换。对于前者,是通过数据总线,由CPU并行地把数据写入控制器,或从控制器中并行地读出数据;对于后者,是设备将数据输入到控制器,或从控制器传送给设备。
轮询方式
- 处理器向控制器发送一个I/O命令
- 如果设备未就绪,则重复测试过程,直至设备就绪
- 执行数据交换
- 等待I/O操作完成后,才可以继续其它操作
中断方式
- 处理器向控制器发出一个I/O命令,然后继续执行后续指令
- 如果该进程不需要等待I/O完成,后续指令可以仍是该进程中的指令
- 否则,该进程在这个中断上挂起,处理器执行其他工作
- 控制器检查设备状态,就绪后发起中断
- CPU响应中断,转向中断处理程序
- 中断处理程序执行数据读写操作
- 恢复执行原先的程序
直接存储器访问(DMA)方式
DMA模块 :模仿处理器来控制主存和设备控制器之间的数据交换
流程:
- 处理器向DMA模块发出I/O命令
- 处理器继续执行其它工作, DMA模块负责传送全部数据
- 数据传送结束后, DMA中断处理器
特点:
- CPU不会终止原程序的执行
- CPU只在数据传送的开始和结束时参与
- 开始时, CPU需要对DMA模块进行初始化
- 结束时, CPU响应中断,但不必保存现场
DMA方式中的周期窃取
当DMA和CPU同时经总线访问内存时, CPU总是将总线的占有权让给DMA一个或几个主存周期
- 周期窃取对延迟CPU与主存的数据交换影响不大
- 数据传送过程是不连续的和不规则的
- CPU大部分情况下与Cache进行数据交换,直接访问内存较少
三种方式的对比
采用轮询方式的设备控制器
CPU需要等待设备就绪,且参与数据传送
采用中断方式的设备控制器
CPU无需等待设备就绪,但响应中断后参与数据传送
通过DMA直接控制存储器
CPU在数据传送开始和结束时参与,与主存进行数据交换时不参与
CPU 作用 | 等待 设备 | 数据 传送 |
---|---|---|
轮询 方式 | 需要 | 参与 |
中断 方式 | 不需要 | 参与 |
DMA 方式 | 不需要 | 不参与 |
I/O通道
设备控制器包含自身专用的处理器和通道程序
- I/O指令不再由处理器执行,而是存在主存中,由
- I/O通道所包含的处理器执行
采用四级连接:处理器,通道,控制器,设备
流程
-
CPU在遇到I/O请求,启动指定通道一旦启动成功,通道开始控制I/O设备进行操作,
-
CPU执行其他任务
-
I/O操作完成后, I/O通道发出中断, CPU停止当前工作,转向处理I/O操作结束事件
CPU与通道并行工作
I/O通道与DMA
与DMA方式不同的是,在DMA方式中,数据的传送方向、存放数据的内存始址以及传送的数据块长度等都由CPU控制,而在通道方式中,这些都由通道来进行控制。另外,DMA方式每台设备至少需要一个DMA控制器,一个通道控制器可以控制多台设备。
- DMA只能实现固定的数据传送控制,而通道有自己的指令和程序,具有更强的独立处理数据输入和输出的能力。
- DMA只能控制一台或者少数几台同类设备,而一个通道可以控制多台同类或者不同的设备。
详见https://www.jianshu.com/p/d1542085afde
###总线与I/O
单总线
将CPU、主存和I/O模块连接到同一组总线上
优点:结构简单,易于扩充
缺点:主存需要和I/O模块共用总线;设备增多会造成总线变长,进而增加传输时延;无法适用于大量高速设备
传统的三级总线
主存和Cache通过主存总线传送数据,主存总线和扩展总线上的I/O设备之间传送数据通过扩展总线接口缓冲
优点:主存与I/O之间的数据传送与处理器的活动分离;可以支持更多的I/O设备
缺点:不适用于I/O设备数据速率相差太大的情形
采用南北桥的多级总线
通过存储总线、 PCI总线、 E(ISA)总线分别连接主存、高速I/O设备和低速I/O设备
优点:可以支持不同数据速率的I/O设备
采用I/O通道的多级总线
支持CPU、主存和多个I/O通道之间的数据传送
支持I/O通道和I/O控制器,以及I/O控制器和设备之间的数据传送
I/O软件
实现层次
设计目标
- 高效率:改善设备效率,尤其是磁盘I/O操作的效率
- 通用性:用统一的标准来管理所有设备
设计思路
把软件组织成层次结构,低层软件用来屏蔽硬件细节,高层软件向用户提供简洁、友善的界面
主要考虑的问题
- 设备无关性:编写访问文件的程序与具体设备无关
- 出错处理:低层软件能处理的错误不让高层软件感知
- 同步/异步传输: 支持阻塞和中断驱动两种工作方式
- 缓冲技术:建立数据缓冲区,提高吞吐率
I/O软件的实现
I/O中断处理程序
位于操作系统底层,与硬件设备密切相关,与系统其余部分尽可能少地发生联系
进程请求I/O操作时,通常被挂起,直到数据传输结束后,并产生I/O中断时,操作系统接管CPU后转向中断处理程序
当设备向CPU提出中断请求时, CPU响应请求并转入中断处理程序
功能
- 检查设备状态寄存器内容
- 判断产生中断的原因,
- 根据I/O操作的完成情况进行相应的处理
如果数据传输有错,向上层软件报告设备的出错信息,实施重新执行
如果正常结束,唤醒等待传输的进程,使其转换为就绪态
如果有等待传输的I/O命令,通知相关软件启动下一个I/O请求
设备驱动程序
包括与设备密切相关的所有代码,从独立于设备的软件中接收并执行I/O请求
-
把用户提交的逻辑I/O请求转化为物理I/O操作的启动和执行
-
监督设备是否正确执行,管理数据缓冲区,进行必要的纠错处理
功能
- 设备初始化
- 在系统初次启动或设备传输数据时,预置设备和控制器以及通道状态
- 执行设备驱动例程
- 负责启动设备,进行数据传输
- 对于具有通道方式,还负责生成通道指令和通道程序,启动通道工作
- 调用和执行中断处理程序
- 负责处理设备和控制器及通道所发出的各种中断
层次
每个设备驱动程序只处理一种设备,或者一类紧密相关的设备
设备驱动程序分为整体驱动程序和分层驱动程序
- 整体驱动程序直接向操作系统提供接口和控制硬件
- 适用于功能简单的驱动程序,效率较高,但较难迁移
- 分层驱动程序将驱动程序分成多层,放在栈中,系统接到I/O请求时先调用栈顶的驱动程序,栈顶的驱动程序可以直接处理请求或向下调用更低层的驱动程序,直至请求被处理
- 用于功能复杂、重用性要求较高的驱动程序,结构清晰且便于移植,但会增加一部分系统开销
独立于设备的I/O软件
执行适用于所有设备的常用I/O功能,并向用户层软件提供一致性接口
功能
- 设备命名:通过路径名寻址设备
- 设备保护:检查用户是否有权访问所申请设备
- 提供与设备无关的数据单位:字符数量,块尺寸
- 缓冲技术:传输速率,时间约束,不能直接送达目的地
- 设备分配和状态跟踪:分配不同类型的设备
- 错误处理和报告:驱动程序无法处理的错误
用户空间的I/O软件
库函数:一部分I/O软件可以使用库函数实现放在操作系统内核之外,运行时与应用程序连接
虚拟设备软件:用一类设备模拟另一类设备的仿真I/O软件,如虚拟光驱
I/O缓冲区
目的
解决CPU与设备之间速度不匹配的矛盾,协调逻辑记录大小和物理记录大小不一致的问题,高CPU和设备的并行性,减少I/O操作对CPU的中断次数,放宽对CPU中断响应时间的要求
缓冲区
在内存中开辟的存储区,专门用于临时存放I/O操作的数据
操作
写操作:将数据送至缓冲区,直到装满,进程继续计算,同时系统将缓冲区的内容写到设备上
读操作:系统将设备上的物理记录读至缓冲区,根据要求将当前所需要的数据从缓冲区中读出并传送给进程
单缓冲
操作系统在主存的系统区中开设一个缓冲区
输入:将数据读至缓冲区,系统将缓冲区数据送至用户区,应用程序对数据进行处理,同时系统读入接下来的数据
输出:把数据从用户区复制到缓冲区,系统将数据输出后,应用程序继续请求输出
双缓冲
使用两个缓冲区
输入:设备先将数据输入缓冲区1,系统从缓冲区1把数据传到用户区,供应用程序处理,同时设备将数据传送到缓冲区2
输出:应用程序将数据从用户传送到缓冲区1,系统将数据传送到设备,同时应用程序将数据传送到缓冲区2
数据从设备输入到缓存区和缓存区输入到用户区就可以同时进行
循环缓冲
操作系统分配一组缓冲区,每个缓冲区度有指向下一个缓冲区的链接指针,构成循环缓冲
解决设备和进程速度不匹配的问题。
这些缓存区为系统公共资源,供进程共享并由系统统一分配和管理
设备独立性
用户通常不指定物理设备,而是指定逻辑设备,使得用户作业和物理设备分离开来,再通过其它途径建立逻辑设备和物理设备之间的映射
比如用户编写程序的时候需要实现打印功能,在实现打印功能的时候不去指定具体的某台打印机,而是只是声明需要打印机,由系统去调配一个打印机
设备管理中需要将逻辑设备名转换为物理设备名,为此系统需要提供逻辑设备名和物理设备名的对应表以供转换使用
优点
- 应用程序与具体物理设备无关,系统增减或变更设备时不需要修改源程序
- 易于应对I/O设备故障,提高系统可靠性
- 增加设备分配的灵活性,更有效地利用设备资源实现多道程序设计
设备的分配方式
独占设备:只能由一个进程独占式使用
分配方式
- 静态分配
在程序运行之前先分配好资源,实现简单,能够防止系统发生死锁,但会降低设备利用率 - 动态分配
提高设备利用率
设备分配的数据结构
设备类表
- 每类设备对应于设备类表的中一栏
- 包括:设备类,总台数,空闲台数,设备表起始地址等
- 支持设备独立性时才会使用
设备表
- 每类设备都有各自的设备表,用来登记这类设备中的每台物理设备
- 包括:物理设备名(号), 逻辑设备名(号),占有设备的进程号,是否分配,好/坏标志等
磁盘
物理结构
磁盘由多个盘片组成
每个盘片被划分为多个同心圆结构的磁道
不同盘片上位于相同位置的磁道构成的圆柱体称为柱面
每个磁道分为固定多个或不等个数的扇区
为了对大量扇区寻址,操作系统将相邻的扇区组合成簇存储文件
物理块(扇区)地址:
-
柱面号,磁头号,扇区号
-
x面y道z扇区
“ x面y道z扇区”中的“面”是指磁头(盘面),不是柱面,扇区是从1开始的
读写数据
读写数据时, 磁头必须定位到指定的磁道上的指定扇区的开始处
过程
- 寻道:控制移动臂到达指定柱面,选择磁头号
- 旋转:等待要读写的扇区旋转到磁头下
- 数据传送
磁盘访问时间=寻道时间+旋转时间+传输时间
驱动调度
移臂调度
使移动臂的移动时间最短,从而减少寻道总时间
先进先出
- 移动臂是随机移动,寻道性能较差
- 按顺序处理请求,对所有进程公平
最短查找时间优先
-
先执行查找时间最短的请求,具有较好的寻道性能
-
存在“饥饿”现象
单向扫描
- 移动臂总向一个方向扫面,归途中不提供服务
- 适用于不断有大量柱面均匀分布的请求的情形
双向扫描
- 移动臂每次向一个方向移动,遇到最近的I/O请求便进行处理,到达最后一个柱面后再向相反方向移动
- 对最近扫描所跨越区域的请求响应较慢
电梯调度
- 无请求时移动臂停止不动,有请求时按电梯规律移动
- 每次选择沿移动臂的移动方向最近的柱面
- 如果当前移动方向上没有但相反方向有请求时,改变移动方向
旋转调度
使得旋转延迟的总时间最少
循环排序
- 通过优化I/O请求排序,在最少旋转圈数内完成位于同一柱面的访问请求
- 旋转位置测定硬件和多磁头同时读写技术有利于提高旋转调度的效率
优化分布
通过信息在存储空间的排列方式来减少旋转延迟
- 交叉因子
如果沿着磁道按序对扇区编号,可能由于磁盘转速太快,造成处理当前扇区的数据时, 下一个扇区已经跳过,需要再转一圈才能继续读数据。因此,对扇区编号时会间隔编号,例如交叉因子为2:1表示相邻编号之间会间隔1个扇区, 3:1表示会间隔2个扇区。 - 按柱面而非盘面进行数据读写
连续记录数据时,先记录在同一柱面的不同磁道上,然后再更换柱面,可以减少数据读写时的移臂操作。
虚拟设备
使用一类物理设备模拟另一类物理设备的技术
eg:内存卡模拟磁盘,块设备模拟字符设备
一个经典的SPOOLing系统
为存放输入数据和输出数据,系统在磁盘上开辟输入井和输出井
井是用作缓冲的存储区域
组成
- 预输入程序:将数据从输入设备传送到磁盘输入井
- 缓输出程序:将数据从磁盘输出井传送到输出设备
- 井管理程序:控制作业和井之间的数据交换
作用
- 预输入:操作系统将作业需要的输入数据成批从输入设备上预先输入至磁盘的输入缓冲区中暂存
- 调度作业执行时,作业使用数据不必再启动输入设备,从磁盘的输入缓冲区读入即可
- 缓输出:作业不启动输出设备,只是将输出数据暂存到磁盘的输出缓冲区
- 作业执行完毕后,由操作系统成批输出
不仅设备利用率提高,作业的运行时间也会缩短,每个作业都感觉各自拥有所需的独占设备
文件管理
文件系统
文件系统是操作系统中负责存取和管理信息的模块,它用统一的方式管理用户和系统信息的存储、检索、更新、共享和保护,并为用户提供一整套方便有效的文件使用和操作方法
文件这一术语不但反映了用户概念中的逻辑结构,而且和存放它的辅助存储器(也称文件存储器)的存储结构紧密相关
功能
文件系统面向用户的功能
- 文件的按名存取
- 文件的共享和保护
- 文件的操作和使用
为了实现这些功能, OS必须考虑:
- 文件目录的建立和维护
- 存储空间的分配和回收
- 数据的保密和保护
- 监督用户存取和修改文件的权限
- 实现在不同存储介质上信息的表示方式、 编址方法、 存储次序, 以及信息检索等问题
文件的存储
卷和块
-
卷是存储介质的物理单位,对应于一盘磁带、一块软盘、一个光盘片、一个硬盘分区
-
块是存储介质上连续信息所组成的一个区域,也叫做物理记录
块在主存储器和辅助存储器进行信息交换的物理单位,每次总是交换一块或整数块信息
外围设备由于启停机械动作或识别不同块的要求,两个相邻块之间必须留有间隙,间隙是块之间不记录用户代码信息的区域
文件的结构
文件的逻辑结构
文件的逻辑结构分为两种形式,流式文件和记录式文件
流式文件
指文件内的数据不再组成记录, 只是由一串依次的字节组成的信息流序列
这种文件常常按长度来读取所需信息,也可以用插入的特殊字符作为分界
记录式文件
是一种有结构的文件,它是若干逻辑记录信息所组成的记录流文件
逻辑记录是文件中按信息在逻辑上的独立含义所划分的信息单位
如,每个职工的工资信息是一个逻辑记录;整个单位职工的工资信息便组成了该单位工资信息的记录式文件
文件的物理结构
文件的物理结构和组织是指文件在物理存储空间中的存放方法和组织关系
文件的存储结构涉及块的划分、记录的排列、索引的组织、信息的搜索等许多问题
顺序文件
将一个文件中逻辑上连续的信息存放到存储介质的依次相邻的块中便形成顺序结构,这类文件叫顺序文件,又称连续文件
优点:顺序存取记录时速度较快
缺点:建立文件前需要能预先确定文件长度以便分配存储空间;修改、插入和增加文件记录有困难
类似于数组
连接文件
连接文件,又称串联文件;连接结构的特点是使用连接字来表示文件中各个物理块之间的先后次序
第一块文件信息的物理地址由文件目录给出,而每一块的连接字指出了文件的下一个物理块位置;连接字内容为0时,表示文件至本块结束
类似于链表
优点:
-
易于对文件记录做增、删、改,易于动态增长记录
-
不必预先确知文件长度
-
存储空间利用率高
缺点:
- 存放指针需额外的存储空间
- 由于存取须通过缓冲区,待获得连接字后,才能找到下一物理块的地址,因而,仅适用于顺序存取
直接文件
直接文件,又称散列文件,它通过计算记录的关键字建立与其物理存储地址之间的对应关系
这种变换通常采用散列法 (hash法)
类似于哈希表
索引文件
索引文件为每个文件建立了一张索引表,其中,每个表目包含一个记录的键(或逻辑记录号)及其存储地址
索引表的地址可由文件目录指出,查阅索引表先找到相应记录键(或逻辑记录号),然后获得数据存储地址
访问方式
索引文件在文件存储器上分两个区:索引区和数据区
访问索引文件需两步操作:
- 查找索引表,
- 获得记录物理地址
需要两次访问辅助存储器,若文件索引已预先调入主存储器,那么,就可减少一次内外存信息交换
特点
优点:索引结构可以被认为是连接结构的一种扩展,除了具备连接文件的优点外,还克服了它只能作顺序存取的缺点,具有直接读写任意一个记录的能力,便于文件的增、删、改
去点:增加了索引表的空间开销和查找时间
文件目录
文件目录结构
文件系统的基本功能之一就是负责文件目录的建立、维护和检索,要求编排的目录便于查找、防止冲突
一级目录结构
在操作系统中构造一张线性表,与每个文件的相关属性占用一个目录项, 构成了一级目录结构
二级目录机构
第一级为主文件目录,它用于管理所有用户文件目录,它的目录项登记了系统接受的用户的名字及该用户文件目录的地址
第二级为用户的文件目录,它为该用户的每个文件保存一个登记栏,其内容与一级目录的目录项相同
每一用户只允许查看自己的文件目录
树形目录结构
每一级目录可以登记下一级目录,也可以登记文件,从而,形成了层次文件目录结构
层次目录结构通常采用树形目录结构,它是一棵倒向的有根树,树根是根目录;从根向下,每一个树分叉是一个子目录;而树叶是文件
一个文件的全名包括从根目录开始到文件为止,通路上遇到的所有子目录路径,又称为路径名
目录的管理
查找
文件查找
“按名存取”文件就是系统根据用户提供的文件路径名来搜索各级文件目录,找到该文件
-
可以从根目录查起(绝对路径名)
-
也可以从“当前目录”查起(相对路径名)
用.表示当前目录, …表示父目录
-
现代操作系统都设置有改变工作目录命令,即变更当前工作目录
目录项查找
搜索具体目录项时,可以采用顺序查找法,依次扫描文件目录中的目录项,将目录项中的名字与欲查找的文件名相比较,可以采用一些优化办法加快查找目录的速度,如二分法,哈希
文件目录处理
树型目录结构存在的一个问题是:当一个文件经过许多目录节点时,使用很不方便;系统在沿路径查找目录时,往往要多次访问文件存储器,使访问速度大大减慢,若把所有文件的目录都复制到主存,访问速度是加快了,但又增加了主存的开销。
一种有效办法是把常用和正在使用的那些文件目录复制进主存,这样,既不增加太多的主存开销,又可明显减少目录查找时间
活动文件表
系统可以为每个用户进程建立一张活动文件表,当用户使用一个文件之前,先通过“打开”操作,把该文件有关目录信息复制到指定主存区域,有关信息填入活动文件表,以建立用户进程和该文件索引的联系
当不再使用该文件时,使用“关闭”,切断用户进程和这个文件的联系,同时,若该目录已被修改过,则应更新辅存中对应的文件目录
文件安全与保护
文件是计算机系统的重要资源,因此, 要求文件系统具有保障文件安全的手段,提供文件保密的措施,有效地实现文件的共享
文件共享
指不同用户共同使用某些文件
并发控制
在允许文件共享的系统中,操作系统应提供手段实现对共享文件的同步控制
- 多个进程可能同时存取一个文件,如果它们同时进行读操作,操作系统应对文件进行公用控制
- 如果有进程进行写操作,例如,有两个进程,进程A要求修改文件,同时进程B要求读出同一文件中的数据,则操作系统必须提供同步控制机制,以保证文件数据的完整性
保密措施
文件保密是指文件及其内容不能被未经文件主授权的其他用户窃取
文件的保密措施有以下几种:
-
隐蔽文件目录
-
设置口令
-
使用**
设置口令指的是打开之前需要输入口令才能打开,但是文件是存储在磁盘上的,所以还可以直接对文件本身使用**进行加密,使得没有**的时候,文件本身内容是无法理解的
文件保护
指防止文件被破坏
文件系统必须要有防止硬软件故障,保存信息完整性的能力,文件副本是主要实现机制
动态多副本技术
在多个介质上维持同一内容的文件,并且在更新内容时同时进行
转储、备份与恢复
定时把文件复制转储到其它介质上,当某介质上出现故障时,复原转储文件
- 一是在一定时间间隔或一个单位处理结束时,系统自动复写更新过的文件和数据
- 二是每天或每周把文件信息全部复写一遍,需要时再通过装入转储文件来恢复系统,诸如BACKUP、 RESTORE等命令
文件保密
指防止文件及其内容被其他用户窃取
文件的存取控制矩阵
系统为每个用户设置访问每个文件对象的存取属性
系统的全部用户对全部文件的存取属性就组成的一个二维矩阵,称为存取控制矩阵
存取控制表
由于操作系统拥有很多用户和众多文件,存取控制矩阵是一个稀疏矩阵,可以将其简化为一张存取控制表
每行包括:用户、文件、存取属性
存取控制表仅登记那些对文件拥有存取属性的部分
基于存取控制矩阵/表的文件保护
存取属性:可以有访问、读、写、执行、创建、删除、授权等
授权就是文件的所有者将文件的权限授权给其他用户
系统通过查阅(矩阵/表)核对用户对文件的存取权限
系统管理用户(超级用户)等同于文件属主权限,并获得对系统文件的授访问权权限
文件属性
存取控制表的一种简化方法是用户分类,再针对每类用户规定文件属性
-
用户分类:属主、合作者、其他
-
文件属性:读、写、执行、 …
-
文件属性可以放在文件目录项中,管理大为简化
-
用户使用文件时, 通过核对文件属性,实现保护
读 写 执行 文件主 1 1 0 伙伴 1 0 0 它用户 1 0 0
文件的存取
操作系统为用户程序提供的使用文件的技术和手段,某种程度上依赖于文件的物理结构
顺序存取
按记录顺序进行读/写操作
读操作根据读指针读出当前记录,同时推进读指针,指向下一次要读出的记录
写操作则设置写指针,把一个记录写到文件未端, 同时推进写指针
允许对读指针进行前跳或后退n(整数)个记录的操作
直接存取
很多应用场合要求快速地以任意次序直接读写某个记录
例如,航空订票系统,用航班号作标识,把特定航班的所有信息存放在物理块中,用户预订某航班时,直接计算出该航班的存位置
索引存取
基于索引文件的索引存取方法
对于这种文件, 信息块的地址都可以通过查找记录键而换算出
实际的系统中,大都采用多级索引,以加速记录查找过程
文件的使用
用户通过两类接口与文件系统联系
-
与文件有关的操作命令
例如,UNIX中的cat, cd, cp, find, mv,rm, mkdir, rmdir等
-
第二类是提供给用户程序使用的文件类系统调用
基本文件类系统调用有:建立、打开、读/写、定位、关闭、撤销
建立文件
用于创建一个文件
所需参数:文件名、设备类(号)、文件属性及存取控制信息
处理流程:在相应设备上建立一个文件目录项, 为文件分配第一个物理块,在活动文件表中申请一个项,登记有关目录信息,并返回一个文件句柄
撤销文件
用于删除一个文件
所需参数:文件名和设备类(号)
处理流程: 若文件没有关闭, 先关闭文件;若为共享文件, 进行联访处理;在目录文件中删去相应目录项;释放文件占用的文件存储空间
如果是共享文件不一定是物理的删除,可能只是对于这个用户来说文件删除了
打开文件
用于建立起文件和用户进程之间的使用联系
所需参数:文件名、 设备类(号)、打开方式
处理流程: 在主存活动文件表中申请一个项,返回一个文件句柄;跟据文件名查找目录文件, 把目录信息复制到活动文件表相应栏;按存取控制说明检查访问的合法性;若打开的是共享文件,则应有相应处理
关闭文件
用于结束一个文件的读写
所需参数:文件句柄
处理流程:将活动文件表中该文件的“当前使用用户数”减1;若此值为0,则收回此活动文件表;完成“推迟写”;若活动文件表目内容已被改过,则应先将表目内容写回文件存储器上相应表目中,以使文件目录保持最新状态
读/写文件
所需参数参数:文件句柄、用户数据区地址、读写的记录或字节个数
处理流程:按文件句柄从活动文件表中找到该文件的目录项信息;根据目录项指出的该文件的逻辑和物理组织方式,把相关逻辑记录转换成物理块
定位文件
用于调整所打开文件的读写指针位置
所需参数:文件句柄,定位指针
辅存空间的使用
磁盘等大容量辅存空间被OS及许多用户共享,用户进程运行期间常常要建立和删除文件, OS应能自动管理和控制辅存空间
随着用户文件不断建立和撤销,文件存储空间会出现许多‘碎片’。OS解决‘碎片’ 的办法是整理‘碎片’;在整理过程中,往往对文件重新组织,让其存放在连续存储区中
分配方式
连续分配:存放在辅存空间连续存储区中(连续的物理块号)
- 优点是顺序访问时速度快,管理较为简单,但为了获得足够大的连续存储区,需定时进行‘碎片’整理
非连续分配:动态分配给若干扇区或簇(几个连续扇区),不要求连续
- 优点是辅存空间管理效率高,便于文件动态增长和收缩
空闲块的管理
位示图
使用若干字节构成一张表,表中每一字位对应一个物理块,字位的次序与块的相对次序一致。字位为“1”表示相应块已占用,字位为“0”状态表示该块空闲
其主要优点是,可以把位示图全部或大部分保存在主存中,再配合现代计算机都具有的位操作指令,可实现高速物理块分配和去配
空闲块成组连接法
把硬盘分为块来管理,然后块分为两类,一类是被占用了的(存储了数据),称为专用块,一类是没有被占用的,称为空闲块,空闲块组成组,如图所示连接在一起
每个空闲块的组最上面一行显示空闲块的数量
每个空闲块组最多100个空闲块,分别编号0-99,其中0号空闲块作为指针,1-99空闲块作为真正使用的空闲块。
每当需要分配空闲块的时候:
if(this.空闲块数 =1 ){ if(this.第一个单元 == 0){ 等待分配空闲块; }else{ x = 一个单元所指向的空闲块组; 分配x的空闲块; x.空闲块数--; } }else if(this.空闲块数>1){ 分配this.空闲块; this.分配空闲块--; }
每当归还空闲块的时候:
if(this.空闲块数<100){ 归还空闲块; this.空闲块数++; }else if(this.空闲块数 == 100){ 空闲块组 x = new 空闲块组(); x.空闲块数 = 1; x.第一个单元 = this; 将空闲块添加到x; x.空闲块数++; }
文件系统的实现层次
并发程序设计
概念
顺序程序设计
每个程序在处理器上执行是严格有序的
程序设计的一般习惯是顺序程序设计:把一个具体问题的求解过程设计成一个程序或者若严格顺序执行的程序序列,这称为程序执行的外部顺序性
特征
- 程序执行的顺序性:程序指令执行是严格按序的
- 计算环境的封闭性:程序运行时如同独占受操作系统保护的资源
- 计算结果的确定性:程序执行结果与执行速度和执行时段无关
- 计算过程的可再见性:程序对相同数据集的执行轨迹是确定的
进程的并发执行
多道程序设计让多个程序同时进入内存去竞争处理器以获得运行机会,OS允许计算机系统在一个时间段内存在多个正在运行的进程,即允许多个进程并发执行。OS保证按照“顺序程序设计” 方法编制的程序在并发执行时不受影响,如同独占计算机。这些按照顺序程序设计思想编制的进程在OS中并发执行属于无关的并发进程。
循环地(从输入机读78秒再计算52秒再向磁带机输出20秒)按照顺序程序设计方法,设计成如下一个程序:while(1) { input, process, output }
处理器利用率: 52/(78+52+20)≈35%
换一种设计思路, 设计3个独立运行的程序,让它们同时进入多道程序系统去并发执行
while(1) { input, send }
while(1) { receive, process, send }
while(1) { receive, output }
处理器利用率: (52n) /(78n+52+20)≈67%
并发程序设计
把一个具体问题求解设计成若干个可同时执行的程序模块的方法
特性
- 并行性:多个进程在多道程序系统中并发执行或者在多处理器系统中并行执行,提高了计算效率
- 共享性:多个进程共享软件资源
- 交往性:多个进程并发执行时存在制约,增加了程序设计的难度
并发进程之间的制约关系
无关的并发进程:一组并发进程分别在不同的变量集合上运行, 一个进程的执行与其他并发进程的进展无关
交往的并发进程:一组并发进程共享某些变量,一个进程的执行可能影响其他并发进程的结果
与时间有关的错误
对于一组交往的并发进程,执行的相对速度无法相互控制。如果程序设计不当,可能出现各种
“与时间有关的”错误。
-
结果错误
两个进程几乎同时对一个数据进行读写,导致数据的读写产生错误
如x中数据为1,A和B都去读并加1写回,可能他们读到的x都是1,当A写回之后,B也写回,最后的结果是B的结果覆盖了A的结果,而如果分开执行就是+2,而最后只+1
-
永远等待
如进程A申请资源的时候,发现没有资源,则进程一直等待,而进程B在此之后归还了资源,但A没有重新查看是否存在资源,则处于一直等待
进程互斥与进程同步
交互的并发进程在执行时必须进行制约,才能保证得到合理的结果
进程互斥:并发进程之间因相互争夺独占性资源而产生的竞争制约关系
进程同步: 并发进程之间为完成共同任务基于某个条件来协调执行先后关系而产生的协作制约关系
临界区
临界资源:互斥共享变量所代表的资源,即一次只能被一个进程使用的资源
临界区指并发进程中与互斥共享变量相关的程序段
多个并发进程访问临界资源时, 存在竞争制约关系。如果两个进程同时停留在相关的临界区内,就会出现与时间相关的错误。
临界区的描述
确定临界资源shared <variable>
确定临界区region <variable> do < statement_list>
两个进程的临界区有相同的临界资源,就是相关的临界区,必须互斥进入
临界区管理的三个要求
- 一次至多允许一个进程停留在相关的临界区内
- 一个进程不能无限止地停留在临界区内
- 一个进程不能无限止地等待进入临界区
临界区的嵌套使用
并非临界区的嵌套使用一定会可能产生死锁,只要申请临界资源的顺序是确定的,就不会死锁
临界区管理
框内的(测试锁、建立锁)两条指令,执行过程不能中断,如果中断就可能产生同时进入临界区或者死锁的状况。
测试并建立指令
TS(x) {
if (x==false) {
x=true; return true;
}else return false;
}
Boolean lock;
lock = false; // 临界区可用
process Pi { // i = 1,2,…,n
Boolean pi;
repeat pi = TS(lock) until pi; // 循环请求锁
临界区;
lock = false; // 解锁
}
对换指令
swap (a,b) { temp=a; a=b; b=temp; }
Boolean lock;
lock = false; //临界区可用
process Pi { // i = 1,2,…,n
Boolean pi;
pi = true;
repeat swap(lock, pi) until !pi; //循环请求锁
临界区;
lock = false; //解锁
}
TS和swap指令均是忙式等待,效率低
中断
简单的解决办法是在进出临界区时开关中断,这样临界区执行就不会中断了,执行就有原子性
关中断; 临界区; 开中断
操作系统原语就采用这种实现思路
但是,临界区的指令长度应该短小精悍,这样才能保证系统效率,不建议用户程序使用, 滥用是可怕的!
PV操作
TS或swap指令管理临界区,采用忙式轮询,效率低
关开中断管理临界区, 不便交给用户程序使用
参考:操作系统访问硬件资源时采用“请求-等待-中断恢复”方式
记录型信号量
一种带数值的软资源
typedef struct semaphore {
int value; // 信号量值
struct pcb *list; // 信号量等待进程队列指针
}
- 每个信号量建立一个等待进程队列list
- 每个信号量相关一个整数值value
- 正值表示资源可复用次数
- 0值表示无资源且无进程等待
- 负值表示等待队列中进程个数
PV操作原语
P操作原语(申请资源)
procedure P(semaphore:s) {
s = s – 1; //信号量减去1
if (s < 0) W(s); //若信号量小于0,则调用进程被置成等待信号量s的状态
}
V操作原语(释放资源)
procedure V(semaphore:s) {
s = s + 1; //信号量加1
if (s <= 0) R(s); //若信号量小于等于0,则释放一个等待信号量s的进程
}
PV操作解决进程互斥问题框架
semaphore s;
s = 1;
cobegin
process Pi {
……
P(s);
临界区;
V(s);
……
}
coend;
PV操作解决进程同步
并发进程为完成共同任务基于某个条件来协调执行先后关系而产生的协作制约关系
一个进程的执行等待来自于其他进程的消息
1生产者1消费者1缓冲区问题
生产者和消费者共享缓冲区
缓冲区有空位时,生产者可放入产品,否则等待
缓冲区有产品时,消费者可取出产品,否则等待
同步关系1:消费者一开始在等待产品到来, 考虑设置一个信号量(等待产品);一开始无产品,初值为0
同步关系2:消费者则在等待缓冲区中有空位, 也可设置一个信号量(等待缓冲区);一开始缓冲区有空位,初值为1
Int B; // 共享缓冲区
Semaphore sput; // 可以使用的空缓冲区数
Semaphore sget; // 缓冲区内可以使用的产品数
sput = 1; // 缓冲区内允许放入一件产品
sget = 0; // 缓冲区内没有产品
process producer {
while(1){
produce a product;
P(sput);//
B = product;
V(sget);//
}
}
process consumer {
while(1){
P(sget);//
Product = B;
V(sput);//
consume a product;
}
}
1生产者1消费者n缓冲区问题
Int B[k]; // 共享缓冲区队列
Semaphore sput; // 可以使用的空缓冲区数
Semaphore sget; // 缓冲区内可以使用的产品数
sput = k; // 缓冲区内允许放入 k 件产品
sget = 0; // 缓冲区内没有产品
Int putptr, getptr; // 循环队列指针
putptr = 0; getptr = 0;
process producer{
while(1){
produce a product;
P(sput);//
B[putptr] = product;
putptr =(putptr+1) mod k;
V(sget);//
}
}
process consumer{
while(1){
P(sget);//
product= B[getptr];
getptr=(getptr+1) mod k;
V(sput);//
consume a product;
}
}
n生产者n消费者n缓冲区
Int B [k];
Semaphore sput; /* 可以使用的空缓冲区数 */
Semaphore sget; /* 缓冲区内可以使用的产品数 */
sput = k; /* 缓冲区内允许放入 k 件产品 */
sget = 0; /* 缓冲区内没有产品 */
Int putptr, getptr; putptr = 0; getptr = 0;
Semaphore s1,s2; /* 互斥使用 putptr,getptr */
s1 = 1; s2 = 1;
process producer_i {
while(1){
produce a product;
P(sput);//
P(s1);//*
B[putptr] = product;
putptr =(putptr+1) mod k;
V(s1);//*
V(sget); //
}
}
process consumer_j {
while(1){
P(sget);//
P(s2);//*
Product= B[getptr];
getptr=(getptr+1) mod k;
V(s2);//*
V(sput);//
consume a product;
}
}
苹果橘子问题
Int plate;
Semaphore sp; /* 盘子里可以放几个水果 */
Semaphore sg1; /* 盘子里有桔子*/
Semaphore sg2; /* 盘子里有苹果 */
sp = 1; /* 盘子里允许放入一个水果*/
sg1 = 0; /* 盘子里没有桔子 */
sg2 = 0; /* 盘子里没有苹果*/
process father {
while(1){
削一个苹果;
P(sp);
把苹果放入plate;
V(sg2);
}
}
process mother {
while(1){
剥一个桔子;
P(sp);
把桔子放入plate;
V(sg1);
}
}
process son {
while(1){
P(sg1);
从plate中取桔子;
V(sp);
吃桔子;
}
}
process daughter {
while(1){
P(sg2);
从plate中取苹果;
V(sp);
吃苹果;
}
}
进程通信
进程通信就是进程之间信息的传递
交往进程通过信号量操作实现进程互斥和同步,这是一种低级通信方式
进程有时还需要交换更多的信息(如把数据传送给另一个进程),可以引进高级通信方式——进程通信机制,实现进程间用信件来交换信息
进程直接通信
发送或接收信件的进程指出信件发给谁或从谁那里接收信件
- send(P, 信件):把信件发送给进程P
- receive(Q, 信件):从进程Q接收信件
进程间接通信
发送或者接收信件通过一个信箱来进行, 该信箱有唯一标识符,多个进程共享一个信箱
- send(A, 信件) : 把信件传送到信箱A
- receive(A, 信件) : 从信箱A接收信件
间接通信的信箱
信箱是存放信件的存储区域,每个信箱可以分成信箱特征和信箱体两部分
- 信箱特征指出信箱容量、信件格式、指针等
- 信箱体用来存放信件,信箱体分成若干个区,每个区可容纳一封信
发送信件原语的处理流程
若指定的信箱未满
则把信件送入信箱中指针所指示的位置,释放等待该信箱中信件的等待者
若指定的信箱已满
发送信件者被置成等待信箱的状态
接收信件原语的处理流程
若指定信箱中有信件
则取出一封信件,释放等待信箱的等待者
若指定信箱中无信件
接收信件者被置成等待信箱中信件的状态
高级进程通信机制
基于流的进程通信
多个进程使用一个共享的消息缓冲区(可称为管道、多路转接器、套接字)
一些进程往消息缓冲区中写入字符流(send/write)
一些进程从消息缓冲区中读出字符流(receive/read)
信息交换单位基于字符流,长度任意
基于RPC的进程通信
采用客户/服务器计算模式
服务器进程提供一系列过程/服务,供客户进程调用
客户进程通过调用服务器进程提供的过程/服务获得服务
考虑到客户计算机和服务器计算机的硬件异构型,外部数据表示XDR被引入来转换每台计算机的特殊数据格式为标准数据格式
外部数据表示XDR就是一个中间格式,客户进程和服务器进程的格式不同在发送的时候用中间格式进行中转
死锁
允许多个进程并发执行共享系统资源时,系统必须提供同步机制和进程通信机制。然而,对这种机制使用不当的话,可能会出现进程永远被阻塞的现象
产生死锁的因素不仅与系统拥有的资源数量有关,而且与资源分配策略,进程对资源的使用要求以及并发进程的推进顺序有关
可从三个方面来解决死锁问题:
- 死锁防止
- 死锁避免
- 死锁检测和恢复
死锁防止
死锁产生的必要条件
- 互斥条件: 进程应互斥使用资源,任一时刻一个资源仅为一个进程独占
- 占有和等待条件:一个进程请求资源得不到满足而等待时,不释放已占有的资源
- 不剥夺条件:任一进程不能从另一进程那里抢夺资源
- 循环等待条件:存在一个循环等待链,每一个进程分别等待它前一个进程所持有的资源
破坏四个必要条件之一,死锁就可防止
破坏第一个条件,把独占型资源改造成共享性资源,使资源可同时访问而不是互斥使用。这是一个简单的办法,但对许多资源往往是不能做到的
采用剥夺式调度方法可以破坏第三个条件,但剥夺式调度方法目前只适用于对主存资源和处理器资源的分配,而不适用于所有资源
静态分配(预分配)
所谓静态分配是指一个进程必须在执行前就申请它所要的全部资源,并且直到它所要的资源都得到满足之后才开始执行
所有并发执行的进程要求的资源总和不超过系统拥有的资源数
采用静态分配后,进程在执行中不再申请资源,因而不会出现占有了某些资源再等待另一些资源的情况,即破坏了第二个条件
层次分配
这种分配策略将阻止第四个条件的出现在层次分配策略下,资源被分成多个层次
一个进程得到某一层的一个资源后,它只能再申请在较高层的资源
当一个进程要释放某层的一个资源时,必须先释放所占用的较高层的资源
当一个进程获得了某一层的一个资源后,它想再申请该层中的另一个资源,那么,必须先释放该层中的已占资源
死锁的避免
当不能防止死锁的产生时,如果能掌握并发进程中与每个进程有关的资源申请情况,仍然可以避免死锁的发生
只需在为申请者分配资源前先测试系统状态,若把资源分配给申请者会产生死锁的话,则拒绝分配,否则接收申请,为它分配资源
银行家算法
系统首先检查申请者对资源的最大需求量,如果现存的资源可以满足它的最大需求量时,就满足当前的申请
也就是系统像银行一样先评估你能不能归还资源,比如给进程A分配了x个资源,则进程A就可以释放所有资源,这样系统的资源数就可以增加了。再看系统里剩余的资源有没有x个,如果没有,那么分配资源给进程A的话,可能最后进程A 也获得不了x资源,则就不会去分配给A资源
eg:假设系统有三个进程P, Q, R,系统只有一类资源共10个,目前分配情况如下:
进程 已占资源 还需要申请数 P 4 4 Q 2 2 R 2 7 现在已经被占用的资源有4+2+2=8个,剩下10-8=2个资源
对P来说:4>2,不能分配资源
对Q来说:2<=2,利用分配资源
对R来说:7>2,不能分配资源
死锁的检测
对资源的分配不加限制,但系统定时运行一个“死锁检测”程序,判断系统内是否已出现死锁,若检测到死锁则设法加以解除
检测的一种方法:可设置两张表格来记录进程使用资源的情况
- 等待资源表记录每个被阻塞进程等待的资源
- 占用资源表记录每个进程占有的资源
进程申请资源时,先查该资源是否为其它进程所占用;若资源空闲,则把该资源分配给申请者且登入占用资源表;否则,则登入进程等待资源表
检测
死锁检测程序定时检测这两张表, 若有进程Pi等待资源rk,且rk被进程Pj占用,则说Pi和Pj具有“等待占用关系”,记为W(Pi, Pj)
死锁检测程序反复检测这两张表,可以列出所有的“等待占用关系”
如果出现W(Pi, Pj), W(Pj, Pk), ……, W(Pm,Pn), W(Pn, Pi)时,显然,系统中存在一组循环等待资源的进程: Pi, Pj, Pk, ……, Pm, Pn,也就是说出现了死锁
进程 | P1 | P2 | … | Pn |
---|---|---|---|---|
P1 | b11 | b12 | … | bn2 |
P2 | b21 | b22 | … | bn2 |
… | … | … | … | … |
Pn | bn1 | bn2 | … | bn2 |
然后这样一个表可以视为使用邻接矩阵表示的有向图,然后判断这个图是不是存在环路,如果存在则则存在死锁
处理
可以采用重新启动进程执行的办法,恢复工作应包含重启动一个或全部进程,以及从哪一点开始重启动
全部卷入死锁从头开始启动,但这样的代价是相当大的,在进程执行过程中定时设置校验点,从校验点开始重执行
中止一个卷入死锁的进程,以后重执行