王道408考研关于I/O部分的笔记

SPOOLing 的核心思想是:
将数据暂时存放在磁盘等中间存储区域,再由专门的后台程序将其送往目标外设(如打印机)(即把低速设备输入的数据提前读到CPU能访问到的高速设备磁盘中,不同进程要输出的数据也是先放到高速设备中,然后设备自己去从中拿,进程就不管这一步)。
数据先保存到中间区域后,CPU 无需等待外设完成操作,可以继续执行其他任务;而外设也可以在空闲时慢慢处理队列中的任务,利于多用户环境。
本质上,假脱机技术是用空间(中间存储)换时间(CPU 效率),并非真的实现了某时刻的共享。它 提高了I/O速度、将独占设备改造为共享设备、实现了虚拟设备功能。
所有用户的任务不会直接发送给物理设备,而是先被暂存到磁盘的假脱机队列中,形成一个有序的任务列表:
输入进程也称预输入进程,将用户要求的数据从输入设备传送到输入缓冲区,再存放到输入井。当CPU需要输入设备时,直接从输入井读入内存。
输出进程也称缓输出进程,把用户要求输出的数据从内存传送并存放到输出井,待输出设备空闲时,再将输出井中的数据经过输出缓冲区输出至输出设备上。
井管理程序:用于控制作业与磁盘之间信息的交换。当作业执行过程中向某台设备发出启动输入或输出操作请求时,由操作系统调用井管理程序,由其控制从输入井读取信息或将信息输出至输出井。
不必深究,也就是说要输入的数据,是提前从输入设备传送过来的,是传到内存后又到外存磁盘的输入井,要输出的数据会先从内存到磁盘的输出井,然后又经过内存的输出缓冲区到输出设备。
image
image

磁盘高速缓存技术提高了磁盘I/O速度,加深CPU和I/O设备的并行性,它利用内存的存储空间来暂存从磁盘读出的一系列盘块中的信息,因此逻辑上属于磁盘,物理上属于内存盘块。
2个形式:内存开辟单独空间作为大小固定的缓冲区;内存未利用的空间作为缓冲池,可供请求分页系统和磁盘I/O时共享
对于前者:主要看单缓冲、双缓冲(再次提高设备和CPU并行程度),略看循环缓冲
单缓冲和双缓冲都用的缓冲区,只不过后者有2个及自己的机制,所以对于一个缓冲区来说,装满才能取走,取完才能装入。
计算公式和时间图,见P321
若两台机器仅配置单缓冲,只能实现一时刻的单向传输,因为此时自己的缓冲区只能作为接受或发送缓冲区,如果是双缓冲区,一个机器的2个缓冲区可以一个接受一个发送,一时刻实现双向发送数据。
循环和缓冲池见P322
高速缓存是保存数据拷贝的高速存储器和我们这的磁盘高速缓存不一样。它与缓冲区区别:高速缓存有的低速设备定有,缓冲区的数据在低速设备(或高速设备)上不一定有备份,可看做“中间暂存”
image
OS内核管理设备独立性、设备驱动程序、中断处理程序
直接涉及到硬件具体细节、且与中断无关的操作肯定是在设备驱动程序层
没有涉及硬件的又对各种设备都需要进行的管理工作都在设备独立性软件层
例如,屏蔽设备间信息交换单位大小和传输速率差异,差错控制,提供统一逻辑块
用户层软件:与用户或应用程序交互,可调用该层的库函数,直接使用设备独立性软件提供的统一接口来发起 I/O 操作。
//用户层 “通过库函数发起 I/O”(方便、简单)→ 库函数 “调用设备独立性接口”(通用、标准化)
负责产生I/O请求、格式化I/O、SPOOLing
设备独立性软件:负责屏蔽不同 I/O 设备的硬件差异,提供统一的接口供上层软件使用,本层解析系统调用参数并根据设备类型调用相应的设备驱动程序。
它实现了设备无关的功能,例如文件系统管理、设备命名与映射(将逻辑设备名转为物理设备名)、缓冲管理和设备保护、错误处理。无论哪种设备,向用户提供的接口应是相同的,如,对各类设备的读/写在应用程序都是read/write命令接口。
例如,操作系统通过设备独立性软件将不同类型的存储设备(如硬盘、USB 驱动器)抽象为统一的文件系统接口,程序只需操作文件路径而无需关心底层设备类型。此外,它还管理设备的分配与释放,避免多个进程同时访问同一设备导致冲突。
设备独立性在于使得应用程序不拘泥于某个具体的物理设备,在应用程序中使用逻辑设备名来请求使用某设备,实际系统执行时将逻辑设备名映射成物理设备名。如此,I/O操作的设备改变时或增删都不用改变应用程序。
小节--设备分配与回收:
设备分配需要考虑设备类型、设备状态、设备安全性(访问权限)及独立性、逻辑与物理名映射关系
设备类型决定设备固有属性,因此不同类型设备要采用不同分配方式
设备状态如占用和空闲等,决定了是否可以被分配给请求进程以及如何处理等待进场
设备安全性如访问权限,决定了哪些进程可以使用哪些设备
命名映射决定了如何通过逻辑地址访问物理地址
逻辑设备表LUT:<逻辑设备名,物理设备名,驱动程序入口地址>(系统设备表的表项)
系统只配置一张系统设备表:所有用户不能使用相同逻辑设备名-单用户系统
每个用户各自一张自己的系统设备表:整个系统则配一张如此表现的设备表--<逻辑设备名,系统设备指针>,如</dev/tty,5>
设备驱动程序:每个设备驱动程序针对特定类型的硬件设备设计,负责将设备独立性软件的通用命令转换为设备能够理解的设备可执行的特定指令,屏蔽设备控制器之间的差异。
是I/O进程与设备控制器之间的通信程序,通常以进程的形式存在。
负责设置设备寄存器、检查设备状态、设置设备工作方式、检查I/O请求合法性(设备保护)、针对不同的硬件将命令解析为指令例如将抽象的盘块号解析为具体的盘面号、磁道号、扇区号。发出I/O命令,若设备忙则阻塞那一套。响应设备控制器的中断请求例如CPU 接收到中断请求后,会暂停当前正在执行的任务,然后根据中断请求的来源,找到对应的设备驱动程序,设备驱动程序接收到 CPU 传递过来的中断信息后,会先判断中断的类型。它会查看中断请求中携带的相关标识信息,来确定这是设备的哪种事件导致的中断。
若更换物理设备,只需要修改设备驱动程序,不需要修改应用程序。
由于设备驱动程序与硬件紧密,不同类型设备不同设备驱动程序,并将程序基本部分固定在ROM。设备驱动程序与所采用的I/O控制方式紧密,常用的有DMA和中断驱动方式。设备驱动程序应允许多次调用。它将抽象的I/O请求(设备无关性软件给的设备操作命令)转为具体操作后传给设备控制器,记录设备状态和完成情况并汇报给请求进程。
中断处理程序:专门处理硬件中断
之前想错了,所谓的中断处理程序,在这里我们讨论外部中断例如外设请求的中断信号,就例如,用户键盘输入,他输入他的,CPU会调度其他进程运行,输入完毕回车后,那自然键盘产生中断请求(注意C语言的scanf函数内执行包含read调用,就是说在执行这个函数的指令时已经系统调用了),响应请求后,已经内核态,CPU执行对应的中断处理程序(对吧,中断的处理)。而且,确实,设备无关层及以下都是内核态,所以一定先调用实际的调用指令,由trap指令进入内核态。而进程阻塞发生在设备无关层。
处理过程:以read命令为例
1.用户要读取某设备内容,软件交互后调用read命令接口
2.调用的接口乃通用接口,每个设备都可响应,设备独立层进行解析,根据设备类型选择相应设备驱动程序,期间有命名映射找到驱动程序入口地址,交往下层
3.驱动程序解析read命令为供自己设备执行的指令,解析完毕就进入中断处理程序
4.执行中断处理程序,中断当前运行进程,转而执行read命令
5.命令到达硬件设备,硬件设备的控制器按照上层传达的命令操控硬件设备
可以发现设备独行性软件和设备驱动程序都解析过read命令,区别:
前者对read命令的解析,是为了根据设备类型找到对应的设备驱动程序,将通用的read请求转化为设备驱动程序能够进一步处理的形式,解析相对较浅,在于确定设备类型并找到对应的驱动程序。
后者将read命令转化为特定设备能够理解和执行的具体指令, 直接控制设备硬件完成实际的读取操作。它需要精确地告诉设备硬件该从哪个存储位置读取数据、读取多少数据等具体操作细节

I/O 操作举例:scanf(“%c”,&d)//尝试用键盘输入赋值d
首先明确:1.函数的第一阶段自然是函数库完成,这里是C语言,scanf()关联用户缓冲区buf 2.缓冲区分为内核态要用的内核缓冲区,和一般用的用户态的用户缓冲区 ,内核空间用来存放OS的代码和数据,供所有进程共享,系统调用函数运行在内核态(系统调用在用户态发生),要先把I/O端口的数据复制到内核空间中(存在内核缓冲区),在系统调用返回前(内核态->用户态),再将数据从内核空间复制到用户空间(复制到用户缓冲区)。
所以第一阶段工作:
1.检查与scanf()关联的用户缓冲区buf,已有数据则直接取用并结束,若为空,则触发系统调用read,以从内核缓冲区中读取数据
2.执行系统调用read,read调用会在执行trap指令前传入本次调用的三个参数:fd(指明输入设备(那个inode存放物理磁盘号..))、buf、count(读取的最大字节数)
然后第二阶段:read调用会展开成一段包含陷阱指令的代码
1.传递系统调用参数,执行trap指令陷入内核态后,执行相应的系统调用服务例程,先会申请一个内核缓冲区,中间不管,会转到设备驱动层,设置相应的I/O参数,进程进入阻塞态并执行CPU调度(注意,驱动程序管它要管的和设备打交道的东西,进程插入阻塞队列和CPU调度只是这会发生的事件)
2.用户通过键盘输入字符,字符被送到键盘I/O接口的数据端口,然后键盘I/O接口向CPU发中断请求,CPU响应中断并执行键盘中断处理程序,驱动程序将字符键盘又送入到内核缓冲区(别忘了,I/O结构,先中断处理程序然后驱动程序)
3.进程被唤醒,插入到就绪队列,等待被调度
4.进程再次获得CPU进入运行态,系统调用服务例程将字符从内核缓冲区复制到用户缓冲区(复制过程肯定还是得内核态下,所以调用返回还在下一步)
5.进程从系统调用返回,之后scanf函数进行字符解析,最后将该字符存储到变量d
过程中,设备驱动程序负责将输入的字符从键盘I/O接口的数据端口送到内核缓冲区;设备无关性软件中的内核程序负责再从内核缓冲区复制到用户缓冲区

磁盘:
一个磁盘有上千磁道,一个磁道按圆心角度划分为上百扇区,一个扇区就是一个盘块被固定大小,所以扇区密度由里向外减少,磁盘存储能力取决于最内道的最大记录密度(不过,现代磁盘已经内外磁道的扇区不一致了)
我们说的磁盘应该是一个磁盘组。扇区是磁盘可寻址的最小单位,簇:一组扇区。
所有盘片上相对位置相同的磁道组成柱面。
磁盘地址可表示为:<柱面号,盘面号(磁头号),扇区号>,地址就是如此,按簇划分也是扇区号,当收到有多个地址就由OS执行调度算法。
如何管理?(磁盘初始化:物理格式化->分区->逻辑格式化)
首先磁盘可以存储数据前必须划分扇区然后才能进行读写,就得物理格式化-->还不能存储文件(也就是存放我们的数据),还要分区、逻辑格式化。
分区:将磁盘分为由一个或多个柱面组成的分区(如C区,D区),每个分区的起始扇区和大小都记在磁盘主引导记录的分区表中(这一过程为磁盘划分出若干逻辑存储区域,每个分区可以独立格式化并使用不同的文件系统)
逻辑(高级)格式化:创建文件系统的根目录等目录结构和分配表,对保存空闲磁盘块信息的数据结构进行初始化,使操作系统能够识别、组织和管理磁盘上的数据
物理格式化是在磁盘物理层面,通常由制造商出厂时完成。逻辑格式化是在物理格式化基础上创建文件系统的过程,如对扇区逻辑编号、建立FAT等。
磁盘只有经过以上步骤后,才能安装系统(即可按照OS)和存储信息。

关于启动:
ROM保存少部分自举代码,完整功能的引导程序在磁盘启动块上,是固定位置,具有启动分区的磁盘成为启动磁盘或系统磁盘。
计算机启动时,初始化硬件并加载操作系统的过程依赖于一系列引导程序。前文提到,磁盘存储文件前需分区,分区信息记录在主引导记录(MBR)的分区表中。
计算机启动流程:
1.激活CPU读取ROM的BIOS程序,IR置为BIOS第一条指令。
2. ROM 中的固件(BIOS)开始运行。不过,还要先在内存构建中断向量表后POST(通电自检)。然后BIOS再初始化硬件,并寻找可启动设备(通常是磁盘),ROM 中的小型自举代码指示磁盘控制器读取磁盘的第 0 号扇区(即 MBR)到内存(这一步是BIOS读取boot,将控制权交给启动顺序排在第一位的存储设备,CPU将该存储设备引导扇区的内容加载到内存)。
3.由第二步加载到内存的MBR(里面包含硬盘分区表与磁盘引导程序Bootloader),扫描解析分区表,找到标有“活动分区”的引导分区(活动分区即为安装了OS的分区),并加载该分区的第一个扇区(称为分区引导记录PBR)
4.执行PBR中的程序,便可找到,加载并激活分区根目录下用于引导OS初始化的程序的程序(启动管理器)
5.由第四步的启动管理器找到 用于引导OS初始化的完整程序后,加载到内存并执行。
image

坏块可以是出厂时就存在的,也可以是由于磁盘的长期使用和磨损导致的。
对坏块的处理实质上就是使用某种机制使系统不去使用坏块。

磁盘存取时间:
寻道的时间是磁盘访问最耗时的部分,调度主要目的在于减少它的所耗时间
注:在磁盘驱动器中,磁道编号通常是从外到内的。磁盘表面被划分为同心圆,这些同心圆称为磁道。最外面的磁道通常被赋予最小的编号(例如,0 号磁道),随着磁道向内圈逐渐增加,编号递增。这种编号方式允许磁盘的读写头更容易地定位到磁道的起始位置,因为磁盘的旋转通常是从外缘开始。
• 寻道时间分两步:Ts=s+m×n
(1) 启动磁头臂消耗的时间s
(2) 移动磁头消耗的时间:假设磁头匀速移动,每跨越一个磁道消耗时间为m,共跨越n条磁道
• 通过旋转磁盘,使磁头定位到目标扇区所需要的时间:Tr=1/2r
1/r就是转一圈所需的时间。找到目标扇区平均需要转半圈,因此再乘以1/2
• 从磁盘读出或向磁盘中写入数据所经历的时间:Tt=(b/N)×(1/r)=b/rN
假设磁盘转速为r,此次读/写的字节数为b,每个磁道上的字节数为N
每个磁道可存N字节数据,因此b字节数据需要b/N个磁道才能存储。而读/写一个磁道所需的时间刚好是转一圈的时间1/r。
综上,平均存取时间Ta=Ts+Tr+Tt

调度算法:评价指标--磁头共移动磁道数、平均寻道长度
各算法图片展示及例子计算2个指标见P343\344
FCFS:调度顺序同请求顺序
如果大量进程竞争使用磁盘,请求访问的磁道可能会很分散;算法在性能上就会显得很差,因为寻道时间过长
请求访问的磁道比较集中的话算法性能还算可以
SSTF(最短寻道时间优先):每次选择当前离磁头最近的磁道
存在饥饿现象,产生饥饿的原因是磁头可能在一小块区域来回移动
是贪心算法的思想,只是选择眼前最优,但是总体未必最优;比FCFS效果好
SCAN(扫描或称电梯调度):在SSTF基础上,规定磁头移动开始方向,并只有磁头移动到最外侧磁道时才能向内移动,或者移动到最内侧再去最外侧(说白了方向上:先..->200(假设最内侧200)再200->0;或先..->0再0->200)
中间部分的磁道会比较占便宜,中间部分相比其他部分响应的频率会比较多,也就是说每个磁道的响应频率存在差异
性能较好,寻道时间较短不会产生饥饿现象
C-SCAN(循环扫描):在SCAN基础上,规定磁头单向,并不是到了某侧后反方向移动,例如到达最外侧0后立刻返回到最内侧200后方向仍不变的移动磁头
相比于SCAN算法,平均寻道时间更长。
对于各个位置磁道响应频率很平均,均匀的等待时间,消除对两端磁道请求的不公平。
LOOK和C-LOOK:分别是SCAN和C-SCAN的改进版,不用到达磁盘最外(内)侧,只需移动到最远(内)端的一个请求(如21)就能返回了.
*****考试时,无特别说明,就是默认SCAN和C-SCAN为其LOOK改进版
小节:以上除了FCFS都会在,当持续存在某个磁道的访问请求均持续满足最短寻道时间优先时,对于其他请求而言一直得不到响应,FCFS才公平。

改善磁盘I/O访问速度的方法:
采用磁盘高速缓存;虚拟盘;采用磁盘阵列RAID;调整磁盘请求顺序(即磁盘调度算法调整请求顺序为实际访问顺序);提前读;延迟写;优化物理块的分布(如按簇对文件分配(注意簇说的是文件分配单位,什么inode等无影响,当然inode个数也受文件数影响))

posted @ 2025-08-19 21:09  niceboy~  阅读(50)  评论(0)    收藏  举报