操作系统


学习《操作系统之哲学原理》

记录一些学习笔记

操作系统历史

1. 状态机

根据特定输入和现在的特定状态进行转态转换,只能做加减法运算。

2. 单一操作员单一控制端操作系统

输入一个命令就执行一个函数库,提供了简单的标准命令供以后使用。

3. 批处理操作系统

计算器总是在等待人的命令,工作效率低下,浪费了昂贵的计算机资源,于是考虑将命令打印在纸带上,
然后交给一个工作人员来一批批处理,把运行结果存储到磁盘上。

4. 多道批处理操作系统

CPU和I/O设备的运行是串行的,在程序进行输入输出时,CPU只能等待。CPU需要不断询问I/O是否完成。
让CPU和I/O并行运行,这就是初衷。

5. 分时操作系统

将程序制作在卡片上,交给管理员来运行,用户无法及时获知程序运行的结果,还有可能管理员会忘记你的程序。
资源公平管理,每个用户可以提交自己的任务。

6. 现代操作系统

个人机开始出现,网络开始普及。此时操作系统各项功能都比较完善了。

内核:系统调度、调度、内存管理、进程管理、VFS框架、内核锁定、时钟和计时器、中断管理、引导、启动、
陷阱管理、CPU管理;可装入模块:调度类、文件系统、可加载系统调用、可执行文件格式、流模块、设备、总线驱动程序等。

计算机硬件

一根总线,其它各种设备挂在总线上,这些设备都有一个控制设备,外部设备都由这些控制器与CPU通信,
这些设备之间的通信需通过总线。

  • 存储架构
存储平均访问延迟平均容量
寄存器1 nsec< 1KB
缓存2 nsec32MB
主存10 nsec128MB ~ 64GB
SSD20 usec40GB ~ 2TB
磁盘(转动)10 msec40GB ~ 2TB
磁带100 sec40GB ~ 500GB

一些概念介绍

  • 中断

设备在完成自己的任务后向CPU发出中断,CPU判断优先级,然后确定是否响应。如果响应,则只需中断服务程序,
并在中断服务程序执行完后继续执行原来的程序。(中断又可以发生中断,中断分为硬件中断、软件中断)

  • 内核态、用户态

为了区分不同程序的不同权限。内核态就是拥有资源多的状态,也称为特权态,用户态访问资源将受限。
运行在内核态的程序可靠性要求、安全性、维护性都要求高,用户态的程序编写相对就比较简单,一般来说
能运行用户态就能完成任务的,就应该运行在用户态。

所谓的用户态、内核态实际上是处理器的一种状态,而不是程序状态。通过设置该状态字,可以将CPU设置为内核态、用户态
或者其他的子态。一个程序运行时,CPU是什么态,这个程序就运行在什么态。

  • 进程、内存、文件

一个程序一旦在计算机运行,它就成为了一个进程。操作系统对进程的管理通过进程表来实现,进程表里存放关于进程的一切信息。
进程的全部资源,包括内存、内核数据结构、软件资源形成一个进程核(core),核快照(core image)代表某一时刻进程的状态。
Linux系统下出现分段错误(segmentation fault)时,操作系统会自动进行核导出(core dump)。

  • 系统调用(system call)

用户程序通过系统调用API来获得操作系统的各种服务。

系统调用按照功能可以划分为6大类:

  1. 进程控制类
  2. 文件管理类
  3. 设备管理类
  4. 内存管理类
  5. 信息维护类
  6. 通信类

调用一般步骤:

result=read(fd,buffer,nbytes);

这个read函数是C语言提供的库函数,这个函数然后调用操作系统的read系统调用

1、参数准备阶段

将所需的参数压入栈,然后调用read库函数,read库函数将read系统调用的代码放在一个约定好的寄存器里,
通过陷入(trap,一种中断方式)将控制权交给操作系统。

2、系统调用识别阶段

操作系统获得控制权后,将系统调用代码从寄存器取出,与操作系统维护的一张系统调用表进行比较,获得read系统调用的
程序体所在的内存地址。之后跳到该地址。

3、系统调用执行阶段

执行系统调用函数,执行完毕后返回到用户程序。

  • 系统调用中的参数传递

上面是将参数压入栈中,其实在x64结构,最前面的8个参数由寄存器传递,只有超过8个参数时,后面的参数才通过栈来传递。

  • CPU指令集

1、X86

是微处理器执行的计算机语言指令集,指一个intel通用计算机系列的标准编号缩写,也标识一套通用的计算机指令集合,属于CISC。

2、X64

又叫x86-64,简称为x64,是64位微处理器架构及其相应指令集的一种,也是Intel x86架构的延伸产品,也是属于CISC。
由AMD设计,后来改名为AMD64,主要是与X86兼容

3、ARM

曾称进阶精简指令集机器(Advanced RISC Machine)更早称作Acorn RISC Machine,是一个32位精简指令集(RISC)处理器架构。

  • 壳(shell)

便于于用户交互,可以是图形界面也可以是文本界面,用户在界面上输入命令,操作系统则执行这些命令。

进程

进程=程序+执行

操作系统对CPU进行管理的重要手段就是进程模型。进程出现的动机是渴望并发,由于需要进程进行分离存储而导致
出现内存管理;由于需要让不同的进程有序的推进,又出现了进程调度。
进程从根本上来说是操作系统对CPU进行的抽象和装扮,因为并发所以发明了进程。

  • 进程模型

从物理内存的分配看来,每个进程占用一片内存空间,进程就是内存的某片空间,由于在任意时刻CPU只能执行一条指令,
所以任意时刻在CPU上执行的进程只有一个,而到底执行那条指令由物理程序寄存器指定。

  • 进程状态

执行态、阻塞态、就绪态

  • 进程管理

进程表:寄存器、程序计数器、状态字、栈指针、优先级、进程ID、信号、创建时间、所耗CPU时间,当前持有的各种句柄等。

  • 进程创建过程

1、分配进程控制块
2、初始化机器寄存器
3、初始化页表
4、将程序代码从磁盘读进内存
5、将处理器状态设置为”用户态”
6、跳转到程序的起始地址(设置程序计数器)

ps:第6步跳转指令是内核态指令,第5步时已经设置为用户态,所以这两步需要硬件帮忙作为一个步骤完成。

  • 进程的缺点

只能在同一时间做一件事情,如果阻塞了,进程就会被挂起,无法执行,线程的出现是为了解决上面的问题。

进程调度

调度是操作系统实现进程模型的根本手段

一般程序使用CPU的模式有3种,计算密集型、IO密集型、介于两者之间

CPU调度就是要达到极小化平均响应时间,极大化系统吞吐率、保持系统各个功能部件处于繁忙状态、提供某种貌似公平的机制。

  • 先来先服务调度算法 FCFS(First Come First Serve)

不能抢占,一个程序一旦启动就一直运行到结束或者阻塞为止。优点是实现简单,缺点是短的工作可能变得很慢,因为前面可能有长时间的工作。

  • 时间片轮转算法

主要针对FCFS的改进,改善短程序的响应时间。周期性的进行进程切换。系统响应时间依赖于时间片的选择(有可能比FCFS还慢)。

  • 短任务优先算法 STCF(Shorted time to Completion Fist)

程序有优先级的区分,短任务的优先级比长任务高。分为非抢占和抢占两个变种,缺点:可能造成长程序无法得到CPU时间而导致”饥饿”。

  • 优先级调度算法

每个进程都有优先级,不止短和长两种优先级。动态调节优先级可以避免低优先级的进程”饥饿”,缺点:响应时间不能保证

  • 混合调度算法

将所有的进程分成不同的大类,每个大类为一个优先级。如果两个进程处于不同的大类,处于高优先级的进程先执行;
如果两个进程处于同一大类,则采用时间片轮转算法

  • 其他调度算法

保证调度(Guaranteed Scheduling)
彩票调度(Lottery Scheduling)
用户公平调度(Fair Share Scheduling Per User)

  • 实时调度算法

动态优先调度(EDF Earliest Deadline First)、静态优先调度(RMS Rate Monotonic Scheduling)

EDF就是最早截止的任务先做,如果新工作来了,比正在进行的程序的截止时间更早,那么就抢占当前进程。

RMS 在进行调度钱先计算出所有任务的优先级,然后按照优先级进行调度,任务执行中既不接收新的进程,也不进行优先级调整和CPU抢占。

进程调度的过程

  • 因时序或外部知道或进程挂起而导致操作系统获得CPU权限

  • 操作系统在所有就绪的进程中按照某种算法选中进程

  • 如果选中的是非当前进程,则操作系统将当前进程(中断或挂起的进程)状态予以保护。

  • 将选中的进程环境设置好(设置寄存器、栈指针、状态字等)

  • 跳转到选中的进程。

调度异常之优先级倒挂(priority inversion)

指的是一个低优先级任务持有一个被高优先级认为所需要的共享资源。这样高优先级的任务因为资源缺乏而处于受阻状态,
一直到低优先级任务释放资源为止。如果此时有其他优先级介于二者之间的任务,并且不需要这个共享资源,则该中介优先级的进程
将获得CPU控制权,从而超越了这两个任务,导致高优先级进程被临界区外的低优先级进程阻塞。

解决办法

  • 使用中断禁止

通过禁止中断来保护临界区,多CPU环境下使用 单一共享标志锁(旋锁)

  • 优先级上限

  • 优先级继承

进程通信

  • 管道

在某种存储介质上划出一片空间,赋给其中一个进程写权限,另一个进程读权限。|,管道的一个重要特点是使用管道的两个进程之间必须存在某种关系(父子),
如果要在两个不相关进程之间使用管道,则需要使用记名管道。

  • 套接字(socket)

按传输媒介可分为 本地套接字(unix)、网域套接字

网域套接字按数据传输特性分为:

  • 数据流(stream)

双向、有序、可靠、非重复数据通信 TCP

  • 电报流(datagram)

双向,不一定有序,尽最大可能交付 UDP

  • 序列包(sequential)

双向、有序、可靠、面向连接、固定最大长度的数据通信,数据端通过接收每一个数据段来读取整个数据包

  • 裸套接字(raw)

提供读取原始的网络协议。这种特殊的套接字可用于手工构建任意类型的协议 ICMP

  • rdm

提供一个可靠的数据层,但不保证到达顺序。一般的操作系统都未实现此功能。

server socket bind listen accept read write
client socket connect read write

  • 信号(signal)

迫使一方对我们的通信立即做出回应,不用建立连接,而是临时决定要与某个进程通信,传输的信息量很小,消耗资源小

  • 信号量(semaphore)

信号量来源于铁路信号系统,相当于旗语,简单的用0 1表示,信号量不止是通信机制,也是一种同步机制

  • 共享内存

两个进程需要共享大量的数据,进程的拥抱

  • 消息队列

相比管道,无需限制进程,任何进程都可以读写,多对多

线程

进程属于处理器级并发,既在处理器这一层次上提供并发的抽象;线程则属于进程级别并发,既在进程这个层次上再次提供一次并发抽象。
将进程分解为线程还可以有效的利用多处理器和多核,可以让不同线程同时运行在不同处理器上。

线程管理

线程控制表

如果某资源不独享会导致线程运行错误,则该资源就由每个线程独享;而其他资源都由进程里面所有线程共享。

共享:地址空间、全局变量、文件、子进程、定时器、信号等

不共享:程序计数器、寄存器、栈、状态字

结合用户态和内核态线程模型,用户态的执行系统负责进程内部线程在非阻塞时的切换,内核态的操作系统负责阻塞线程的切换。
其中内核态的线程较少,用户态的线程数量多,每个内核态线程可以服务多个用户态线程。

  • 线程同步

线程同步的目的就是不管线程之间的执行如何穿插,其运行结果都是正确的,或者说保证多线程执行下的结果确定性。

内存

内存管理从根本上说是操作系统多存储设备进行的抽象和装扮,程序的地址独立性、地址空间的保护、内存空量的巨量或无限扩大、内存服务速度的大幅度提升

内存管理的目标:

  • 地址保护

一个程序不能访问另一个程序地址空间

  • 地址独立

程序发出的地址应与物流主存地址无关

- 虚拟内存

虚拟内存的中心思想是将物理主存扩大到便宜、大容量的磁盘上,即将磁盘空间看做主存空间的一部分。

  • 静态地址翻译(单道编程)

运行前即将物理地址计算好的方式叫做静态地址翻译,优点是程序运行速度快,缺点1是整个程序要加载到内存空间去,比物理内存大的程序无法运行,
缺点2是只运行一个程序造成资源浪费,如果一个程序很小,剩下的内存空间也无法使用,缺点3是可能无法在不同的操作系统下运行。

  • 动态地址翻译

在程序加载完毕后才能计算物理地址,也就是在程序运行时进行地址翻译。

  • 固定分区内存管理

采用多个队列,每个分区对应一个队列,大的程序进分区大的队列,小的程序进分区小的队列

物理地址=虚拟地址+程序所在区域的起始地址(基址)

地址保护也就是 基址 <= 有效地址 <= 极限(基址+程序长度)

使用两个寄存器来存放,基址寄存器、极限寄存器

硬件只需要一个加法器和一个比较器

缺点是,如果还有空闲分区,但是等待的程序不在该分区的队列上,有空间也不能运行程序。
地址空间无法增长,如果程序在运行时需要增长怎么办?

  • 非固定分区内存管理

除了划分给操作系统的空间外,其余内存作为一个整体。程序像叠罗汉一样,程序内存增长是一个问题

通常程序空间增长的来源:数据和栈,最简单的方式是数据和栈往一个方向增长,预先给数据部分和栈分别留下增长空间,优点是独立性高,空间利用率可能会低。
另一个是让数据和栈往相反的方向增长,这样只要本程序的自由空间还有多余,不仅可以进行函数调用,又可以增加新的数据。

当一个程序所占的空间不够时,将其倒到磁盘上,再加载到一片更大的内存空间,这种方式叫做交换(swap)

如果一个程序超过了物理内存,还能运行吗?答案是能,重叠(overlay)将程序按照功能分成一段一段功能相对完整的单元。
一个单元执行完后,再执行下一个单元,后面执行的单元可以覆盖前面执行过单元。

  • 双基址

使一个程序代码部分能够共享,数据可以分开,数据和代码分别用一组基址和极址表示。

- 分页内存管理

分页系统的核心就是将虚拟内存空间和物理空间划分为大小相同的页面,如4KB、8KB等,以页面作为内存空间的最小分配单位,
一个程序的一个页面可以任意存放在任意物理页面。

一个程序发出的虚拟地址由两部分组成:页面号和页内偏移值

虚拟地址通过MMU翻译,将虚拟页面号翻译成物理页面号,偏移值无需操作。
对于每个程序,内存管理单元都为其保持一个页表,改页表中存放的是虚拟内存到物理页面的映射。

对于无效的页面访问,需要终止发出该访问的进程。
对于合法但不存在物理内存的页面,我们通过缺页中断将该虚拟页面放进物理内存。
对于受保护的页面,同样终止该进程。

分页系统的缺点:页表很大,32位寻址,页面尺寸为4KB的分页系统来说,页表将有1048576个记录,每个记录要多占一个字节。

  • 多级页表

如两级页表,一个虚拟地址分为3部分,前10位表示顶级页表,中间10位表示次级页表,后面是页内偏移值12位。
顶级页表保存在内存,次级页表放到磁盘,内存占用少,缺点是系统速度下降,一次内存访问变成了三次。

  • 反转页表

存放物理地址到虚拟页面的映射。虚拟地址未64位,页面尺寸4KB,物理内存256MB,则虚拟页面数为2^52,而物理页面数只有2^16
反转页表后,可以节省空间。

寻址发出的虚拟地址,这个可以将虚拟页号散列到物理页号,然后以散列出来的物流页号作为索引,在反转页表里面查找。

  • 翻译快表TLB(Translation Look Aside Buffer)

将虚拟地址翻译的结果放到缓存里,再次访问时无须再次翻译(如果一个页面被访问,则该页面的其他地址可能也将随后访问)

Linux 使用三级页表 Linux的TLB命中率很高

  • 缺页中断处理

1、硬件陷入内核
2、保护通用寄存器
3、操作系统判断所需的虚拟页面号
4、操作系统检查地址合法性
5、操作系统选择一个物理页面来存放将要调入的页面
6、如果选择的物流页面包含有为写的磁盘内存,则首先进行写盘操作
7、操作系统将新的虚拟页面调入内存
8、更新页表
9、发生缺页中断的程序进入就绪状态
10、恢复寄存器
11、程序继续

- 页面更换

如果物理内存已满,则需要挑选某个已经使用过的页面进行替换。

公平算法:随机算法、FIFO、第二次机会算法、时钟算法

非公平算法:最优算法、NRU算法、LRU算法、工作集算法

  • 随机算法

随机产生一个页面号进行替换,当然效果很差。

  • FIFO

更换最早进入内存的页面,使用链表将所有再内存的页面按照进入时间链接。如果最先加载进来是频繁访问的页面,会降低效率。

  • 第二次机会算法

FIFO更换页面时,判断该页面最近是否被访问过,如果没有则替换,如果被访问,则将该页挂到链表末端,时间设置为当前时间,访问位清零。

  • 时钟算法

第二次机会算法需要移动链表,页面访问位只在页面替换进行扫描时才清零。维护一个时钟索引的链表,每次替换时时针转动
如果当前页面的访问位为0,替换该页面。缺点是没有考虑不同页面调用频率不同。

  • 最优算法

选择一个再也不会被访问的页面进行替换,最优算法是目的,其实是有一种无法实现的算法,谁的算法最接近最优算法,谁就是最好的。

  • NRU算法(Not Recently Used)

在第二次机会算法上改进,选择一个最近没有被访问的页面来替换,在最近没有被访问页面,按照各页面的修改位和访问位组合来进行划分。

根据时空局域性原理,一个最近没有被访问的页面,在随后的时间里也不太可能被访问。

根据修改位和访问位,可以有4种组合,根据组合来替换,最先是未访问未修改,以此类推。

  • LRU算法(Least Recently Used)

优化NRU,不仅考虑最近是否使用,还要考虑使用频率。使用矩阵来实现,记录页面的使用频率和时间

n是相关程序当前在内存的页面数,开始时矩阵初始值为0,每次页面被访问时,例如第k个虚拟页面被访问,进行如下操作:

1、将第k行的值全部置1
2、将第k列的值全部置0

每次需要更换页面时,选择矩阵里对应值最小的页面进行替换即可,此处的取值是把该行所有的01连起来看重一个二进制数

使用位移寄存器实现LRU,减少矩阵的内存占用。
给每个存放在内存的页面配备一个位移寄存器,该寄存器用来记录该页面被访问的频率和最近属性,初始值为0
然后再每个规定长度的周期内,将位移寄存器的值往右移动一位,并将对于页面的访问位的值加到该位移寄存器的最左位,
每次需要更换页面时,只需要寻找对应位移寄存器值最小的页面即可。
位移寄存器的长度的意义就是决定”最近”这个时间段的长度,溢出位不做考虑,因为属于超时信息,时间发生越久远的事情,它对决策的影响越小。

  • 工作集算法

LRU算法虽然很好,但实现成本高,而且时间代价大。
我们真的需要为每个页面保留每次访问的记录才能找到一个合适替换的页面吗?

只维持少量的信息使我们选出的替换页面不太可能是马上又会使用的页面即可。

程序访问的时空局限性:在一段时间内,程序访问的页面将局限在一组页面集合上。
例如,最近k次访问均发生在某m个页面上,那么m就是参数为k是的工作集。我们用w(k,t)来表示在时间t时k次访问所涉及的页面数量。

为页表的每个记录增加一项信息用来记录该页面最后一次被访问的时间。这个时间不必是真实的实际,只要是按规律递增即可。
同时设置一个时间t,如果一个页面的最后一次访问在当前时间减去t之前,则视为工作集外。

具体操作:

1、如果一个页面的访问位为1,则将该页面的最后一次访问时间设为当前时间,并将访问位清零

2、如果页面的访问位为0,则查看其访问时间是否在当前时间减去t之前,如果在,则该页面将是被替换页面,算法结束。
如果不在,记录当前所有被扫描过的页面的最后访问时间里面最小值,扫描下一个页面并重复1、2

  • 工作集时钟算法

工作集算法的缺点是没错扫描页面进行替换时,有可能需要扫描整个页表。并不是所有页面都在内存里,因此一大部分是无用功,
另外由于其数据结构是线性的,造成没错都按同样的顺序进行扫描,对后面的页面不公平。
结合时钟算法,使用工作集算法原理,但是将页面扫描顺序按照时钟的形式组织起来。

段式内存管理

分页系统,共享困难,一个页面很可能既包含代码又包含数据,一个页面只要有一行地址是不能共享的,这个页面就不能共享。
一个进程只能占有一个虚拟地址空间,也就是一个程序的大小最多只能和虚拟空间一样大,这个缺点在编译器上得到体现,
编译器在工作时需要保持多个数据结构:词法分析树、常数表、代码段、符号表、调用栈,而这些数据结构可以独立增长和收缩。
这样就可能造成不同的数据结构需要空间时,碰到其他数据结构导致无法增长,编译就会失败。

这里的碰撞是在虚拟空间,解决的办法就是增加虚拟空间,而分页系统只使用了一个虚拟地址空间,自然解决不了这个问题。

分段管理就是将一个程序按照逻辑单元分成多个程序段,每个段使用自己单独的虚拟地址空间。
对于编译器来说,可以给其分配5个段,占用5个虚拟地址空间。

要区分一个虚拟地址所在的段,须在虚拟地址前面加一个前缀,即该地址的段号。一个地址由段号、段内偏差构成。

与前面的基本内存管理类似,每个段由一组基址、极限组成。

段号是否需要占用寻址位数,如果是则每个逻辑段实际上不能占用一个完整的虚拟地址,一般断号不会超过3位,
如果想分配逻辑段完整的虚拟地址空间,则可以将虚拟段号放到一个特殊的寄存器,或者隐含在指令的操作码里。

  • 段页式内存管理

将程序分为多个逻辑段,每个段里进行分页,即将分段和分页组合起来。

段表+多级页表

1、基本内存管理模式:将一个程序作为一整段进行管理,形成了纯粹分段(固定加载地址、固定分区、非固定分区、交换)

2、页式内存管理:一个程序分为很多固定大小的页面,使用页表来管理

3、逻辑分段:程序按逻辑分段,用一组基址、极限来管理段,放在段表

4、段内分页:程序按逻辑分段,每一段进行分页,使用段页管理

文件管理

文件系统从根本上是操作系统对磁盘进行抽象和装扮。

每块盘面分为磁道和扇面,磁道是一个个同心圆,每个磁道又被分为扇面(扇区),数据则以扇面进行存储,扇面是磁盘IO的最小单位。

扇面内容通常分为:标题(同步信息、位置信息)、数据、ECC纠错信息

格式化:将原始的磁道和扇面信息存入盘面,并对盘面进行检查以判断数据是否可以写入每个扇面或从其读出。如果某个扇面确认被损坏,
即使使用ECC的情况也不能使用该扇面,则格式化过程将对这个扇面进行标记,避免使用这个扇面。

磁柱:所有盘面上处于同一位置的磁道构成,如果一个磁盘驱动器有8个盘片,则这个磁盘的一个磁柱由16个磁道构成

  • 访问速度

1、寻道时间(seek time):把读写磁头移动到所要求的磁道位置所需的平均时间,通常在8~20ms

2、磁道到磁道的访问时间(track to track time):磁头移动相邻磁道所需的时间,通常在2~3ms

3、旋转延迟时间:磁头到达所要求的磁道位置后,等待所要求的扇面旋转到磁头下方的平均时间。3ms~8.57ms,根据转速计算

4、平均访问时间:寻道时间+旋转延迟

5、爆发速度:磁头到达所需扇面后,磁盘驱动器输出或接收数据的最大速度

6、可持续数据速度:在一段可持续时间内数据可以被访问的速度,对大文件的访问非常重要

  • 磁盘调度算法

先来先服务FCFS、短任务优先STF、短寻道优先SSF、电梯调度ES、提前查看电梯调度ESLA、单向电梯调度OWES

  • 固态盘SSD(Solid State Disk)

文件系统

目标:地址独立、地址保护

  • 系统启动

磁盘的扇面充0递增,第0个扇面存放主引导记录(Master Boot Record),该记录的内容是一个小小的程序,用来启动计算机。
MBR之后是磁盘分区表,里面存放磁盘的所有分区及其开始和终止地址,其中一个区为主分区。操作系统就装载在这个分区,
主分区里面最前面的是引导记录(Boot Record)

计算机启动时,处于主板ROM里面的BIOS程序首先运行,BIOS执行一些基本的系统配置扫描后对磁盘的扇面0进行读操作,
将MBR里面的程序读到内存并运行,MBR程序接下来找到系统主分区,并将BR加载并运行

I/O原理

I/O软件分层

  • 用户层I/O软件

  • 设备独立的操作系统软件

  • 设备驱动程序

  • 中断服务程序

中断服务程序是I/O软件分层的最底层,设备驱动程序负责中断响应,即设备驱动程序启动I/O操作后阻塞,然后等待中断

中断处理步骤:
1、保存没有被中断硬件保存的相关寄存器
2、设置中断服务程序上下文
3、设置中断服务程序的栈
4、回应中断控制器
5、重开中断
6、从保存处恢复寄存器
7、执行服务程序
8、设置MMU以执行下一个进程
9、设置新进程的寄存器
10、开始执行新进程

  • 设备驱动程序

任务:
1、从上层接收抽象的读写请求
2、确保读写操作完成
3、初始化设备、开关设备
4、对设备的功能进行管理


本文不允许转载。
  目录