操作系统类型

  • 单批道处理:内存中同时只有一道程序运行,程序之间只能串行

  • 多批道系统:允许多个程序并发运行,操作系统正式诞生,但是对cpu等资源来说,同一时间还是只服务一个进程,但是一旦空闲,就会立马被其他进程占用,即便上一个进程未结束,但是因为已经不需要cpu所以无碍,这样大大提高了资源的利用率;缺点是人机交互不好。

  • 分时操作系统:操作系统以时间片为单位,轮流为各个用户/作业服务;用户请求可以被即时响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在;缺点是无法区分任务的紧急性

  • 实时操作系统:能够优先响应一些紧急任务,某些紧急任务不需时间片排队。在实时操作系统的控制下,计算机系统接收到外部信号后及时进行处理,并且要在严格的时限内处理完事件。实时操作系统的主要特点是及时性可靠性

虚拟机管理程序(VMM)

传统计算机上,一台计算机只能运行一个操作系统,为了充分利用硬件资源,我们希望在一台计算机上运行多个操作系统

通过虚拟机管理程序,把一台物理机器虚拟化为多台虚拟机(VM)每台虚拟机上都能独立运行一个操作系统

虚拟机管理程序又可分为两大类,第一类,虚拟机管理程序直接运行在硬件上,可移植性差;第二类,虚拟机管理程序运行在宿主操作系统上,可移植性高。

操作系统功能

  • 处理机(cpu)管理:处理机管理主要是指对中央处理器(CPU)的工作进行有效的组织和调度,以提高系统的效率。这包括进程控制、进程同步、进程通信和进程调度等。通过合理的调度算法,操作系统确保每个进程都能公平地获得CPU时间,并高效地完成任务。
  • 内存管理:对应课程中的内存管理一章,包含分页,分段,虚拟内存等知识
  • 文件管理:对应课程中的文件管理一章,包含磁盘调度算法,文件属性等知识,文件管理可以理解为外存管理
  • 设备管理:比如I/O设备管理
  • 作业管理:

中断

作用

让cpu从用户态(也叫目态)变为内核态,是内核程序夺回cpu控制权的唯一途径;进程的并发离不开中断。

分类

根据中断发生的位置不同,可以把中断分为外中断和内中断。

内中断(异常)

内中断也称为异常(Exception),是指由处理器内部产生的中断信号,通常是因为执行指令时遇到特殊情况或错误而引起的。内中断主要包含以下几种类型:

  • 故障(Fault):这种类型的中断表示发生了某种可恢复的错误,比如除以0。CPU会在发生故障后保存现场,并尝试修正问题,然后返回原程序继续执行。
  • 陷入(Trap):程序故意引发,比如用户进程请求调用操作系统服务(系统调用)。
  • 终止(Abort):表示发生了严重的、不可恢复的错误,导致程序无法继续执行,如硬件故障。

外中断

外部指令提醒cpu中断,目的是通知CPU有外部事件需要处理,然后cpu进入内核态(运行内核程序的状态),处理收到的中断信号,包括时钟中断(它由硬件定时器周期性地产生,用于维持系统时间、调度进程等关键功能)i/o中断(i/o操作完成)

用户态/内核态

  • cpu的状态有两种,用户态和内核态;
  • 处于用户态的时候运行的是用户进程,只能访问用户空间,不能直接访问系统空间
  • 处于内核态的时候运行的是内核程序,能访问任何内存空间
  • 可以通过中断来切换这两种状态

中断程序

cpu根据不同的中断信号执行不同的中断程序,本质是内核程序,运行在内核态(也叫管态)

中断嵌套

当CPU正在处理一个优先级较低的中断,又来了一个优先级更高的中断请求,则CPU先停止低优先级的中断处理过程,去响应优先级更高的中断请求,在优先级更高的中断处理完成之后,再继续处理低优先级的中断,这种情况称为中断嵌套,因为低级中断的处理过程被高级中断插入了(低级中断-高级中断-低级中断),所以叫做中断嵌套。

中断屏蔽

CPU通过指令限制某些设备发出中断请求,处理中断一般按照中断的优先级对其进行处理,某些时候可以屏蔽掉高优先级的中断,中断产生时系统不予响应,未被屏蔽的低优先级中断反而可以响应,从而改变了中断响应次序 ,这样处理中断就更灵活些了。

进程

是操作系统进行资源分配调度的独立单位

特性

  • 动态性:最基本的特性
  • 异步性:强调并发运行的进程之间的执行先后顺序是不可预知
  • 并发性:没有并发就没有异步,现代操作系统中进程是并发执行的

并发/并行/异步

  • 异步:并发的进程以独立的,不可预知的速度向前推进。异步性基于进程并发
  • 并发:在同一时间间隔内运行多个进程。宏观看起来同时,实际上是通过快速切换进程来模拟同时执行的效果。
  • 并行:多个进程的同时执行

程序与进程的区别

程序是静态的,可执行文件的集合,而进程是动态的。

进程组成

  • PCB:也叫进程控制块,包含了进程相关的所有信息,是进程存在的唯一标识;方便操作系统管理进程,进程结束会被回收。

    • pid:每次新建进程,都会给进程分配一个唯一的pid,用来标识不同的进程

    • 其他进程有关的信息

  • 数据段:程序中定义的变量

  • 程序段:程序代码

程序段和数据段本身是静态的,但是为进程的动态执行提供的必要的代码和数据基础,它们在进程运行过程中的使用和变化(比如数据的读写)反应了进程的动态性。

进程之间的基本关系

  • 同步:协调进程间的执行顺序,为了解决异步问题,属于直接制约关系
  • 互斥:避免多个进程同时访问同一资源导致冲突,互斥访问临界资源属于间接制约关系,因为中间夹了一个临界资源

进程同步-PV操作

p用来代表wait原语,v用来代表signal原语;使用原语的好处是检查和上锁是一气呵成的;

  • 整形信号量:存在循环等待,不满足让权等待,因为资源不足会进程会循环等待资源。
  • 记录型信号量:在整形信号量的基础上多了一个等待队列p操作让资源数减一,如果资源数<0(先减一再判断,说明没有空闲资源了),使用block原语阻塞进程,放入等待队列;v操作让资源数+1,如果资源数<=0,说明有进程正在等待资源,则使用wakeup原语唤醒一个进程;
  • 进程同步的时候指定某个资源的数量为0,然后先v后p,即先要执行的进程释放一个资源后,才能运行另一个进程,因为后执行的进程需要这个资源,也就是说,如果一个进程需要另一个进程执行完后才能运行,就能实现进程的同步。

进程通信

进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存空间相互独立,进程之间的通信是有一定的延时的。

为了安全起见,进程之间不能直接通信,需要借助操作系统。

共享地址空间

就是给需要通信的进程分配一个能够共享的内存空间,特点是写入,取出数据可以是在共享空间的任意位置的;为避免出错,各个进程对共享空间的访问应该是互斥的。

消息传递

通过sendreceive原语操作实现

直接传递

指明发送到哪个进程,接收哪个进程的信息,消息存储在进程的消息队列(存储着所有发送给这个进程的消息)中,消息队列存储在PCB中,进程PCB存储在操作系统内核空间中。

间接传递

指明发送到哪个邮箱,接收哪个邮箱的信息(邮箱存储在操作系统内核)

管道

半双工,同时只能存在一个方向(水管中的水流也只能是单向的);本质是一个共享的文件,进程向操作系统申请后由操作系统来分配;管道通信逻辑上是个循环队列(一端写满了,如果另一端没满,可以往另一端继续写);区别于共享内存的方式,读入,取出数据都是有限制的。

管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个管道。

管道写满的时候,写进程阻塞,管道为空的时候,读进程阻塞。

进程状态转换

  • 创建态:进程已被创建
  • 就绪态:进程已被创建,随时可以上cpu执行
  • 运行态:进程正在cpu上运行,一个进程占用一个cpu(当前电脑虽然通常只有一个cpu,但是这个cpu是多核的,可以同时运行多个线程或者说进程)
  • 阻塞态:当进程请求某个资源但是该资源被占用时,进程下cpu,变成阻塞态
  • 终止状态:进程运行结束

进程调度算法

先来先服务

先来先上cpu运行,对短作业不友好(上厕所,你急着上小号但是里面有人在上大号);非抢占式算法。

短作业优先

  • 对长作业不友好,面对远远不断的短作业,可能会导致长作业出现饥饿问题
  • 一般是非抢占式的,也有抢占式的;
  • 是平均周转时间最短的算法(平均周转时间=(总运行时间+总等待时间)/进程数目);因为各个进程运行时间是固定的,这种算法能让所有进程的总等待时间最短,所以能实现最短的平均周转时间。

高响应比优先算法

既考虑到了等待时间也考虑到了进程长度;一个进程结束时,计算就绪队列中所有进程的响应比,让响应比最高的进程上cpu;不会导致饥饿。进程响应比等于:1 + 等待时间/进程运行时间

时间片轮转算法

每个进程分配一个固定的时间段,让它们轮流执行。系统维护一个就绪队列,其中包含所有等待CPU时间的进程。当一个进程的时间片结束时,无论它是否已完成,都会被移到队列的末尾,下一个进程开始运行。如果进程在时间片内完成,则从队列中移除。

确保所有进程都能获得一定的CPU时间,避免了饥饿现象。但要注意的是,频繁的上下文切换(进程切换)可能会带来额外的系统开销,尤其是当时间片设置得过短时

优先级调度算法

每个进程都被赋予一个优先,系统总是选择当前具有最高优先级(最低数字通常表示最高优先级)的进程执行

其他调度

  • 进程调度(低级调度):让就绪状态的进程将获得处理机的过程;发生频率最高的调度

  • 内存调度(中级调度):把内存中的暂时不需要的进程换出,或者把外存的已具备运行条件的就绪进程重新调入内存。暂时调到外存等待的进程状态为挂起状态。被挂起的进程PCB会被组织成挂起队列。就拿手机举例,我们打开后台的某个应用,有的进入的很快,有的进入的很慢,这是因为,因为内存不足,有的后台应用进程已经被移出内存(挂起)了,所以再次进入的速度很慢,而还要一部分后台应用进程还保留在内存中(阻塞态),所以进入速度很快。

  • 作业调度(高级调度):把作业调入内存,就是让一个程序执行,为其创建进程,是发生频率最低的调度。

线程

背景

  • 虽然进程之间可以并发执行,但是传统的单个进程只能串行的执行一系列代码,这就导致一个进程无法同时执行多个功能。一个进程内部可以根据功能不同划分多个线程,线程之间可以并发运行;比如我们打开qq,既能发送文件,又能和别人语音聊天。

  • 引入线程后,进程只作为除CPU之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的),但不再是调度(上cpu)的基本单位,线程才是。

线程的属性

  • 线程是处理机调度的单位
  • 多核CPU计算机中,各个线程可占用不同的内核
  • 每个线程都有一个线程ID线程控制块(TGB)
  • 线程也有就绪、阻塞、运行三种基本状态
  • 线程几乎不拥有系统资源;同一进程的不同线程间共享进程的资源
  • 由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预,直接使用共享的地址空间就好。
  • 同一进程中的线程切换,不会引起进程切换
  • 不同进程中的线程切换,会引起进程切换
  • 切换同进程内的线程,系统开销很小;切换进程,系统开销较大

死锁

所有进程都在等待其他进程释放资源,导致所有进程都阻塞的状态

必要条件

  • 互斥条件:只有对临界资源的争抢才会引发死锁,如果资源可以同时被多个进程访问,那就不存在资源的争抢问题
  • 不可剥夺条件:进程在获取到所需资源但是还没有使用之前,所占有的资源是无法被其他进程剥夺的,只能主动释放
  • 请求和保持:进程会保留已经获得到的资源,并继续请求需要的,未获得到的资源。
  • 循环等待:每个进程在请求别的进程占有的资源的同时,已经获得的资源也被其他进程请求。

处理方法

不允许死锁发生

  • 预防死锁:破坏必要条件

    • 破坏互斥:把临界资源改造成可以同时使用的资源,比如spooling技术,然而并不是所有的资源都可以改造成可共享使用的资源。并且为了系统安全,很多地方还必须保护这种互斥性。因此,很多时候都无法破坏互斥条件。
    • 破坏不可剥夺:当某个进程请求新的资源得不到满足时,它必须立即释放保持的所有资源,待以后需要时再重新申请。也就是说,即使某些资源尚未使用完,也需要主动释放,从而破坏了不可剥夺条件。但这种策略也有很多缺点。
    • 破坏请求和保持:可以使用静态分配法,进程在运行前一次性申请所有所需资源,如果申请未满足,就不把进程投入运行,一旦申请通过,整个运行过程中都占用这些资源;因为申请的资源多,所以可能因为条件一直得不到满足而造成进程饥饿。
    • 破坏循环等待:使用顺序资源分配法,给资源编号,进程必须按照编号递增的规则请求资源。首先,系统中的每种资源都被赋予了一个唯一的编号。例如,如果系统中有打印机、磁带机和硬盘三种资源,则可以分别为它们分配编号1、2、3。P1首先请求并获得了编号为1的打印机资源。根据顺序资源分配法,P1接下来只能请求编号大于1的资源(即磁带机或硬盘),而不能再请求打印机。
  • 避免死锁:银行家算法

    所谓安全序列,就是指如果系统按照这种序列分配资源,则每个进程都能顺利完成。只要能找出一个安全序列,系统就是安全状态。当然,安全序列可能有多个。

    如果分配了资源之后,系统中找不出任何一个安全序列,系统就进入了不安全状态。这就意味着之后可能所有进程都无法顺利的执行下去。当然,如果有进程提前归还了一些资源,那系统也有可能重新回到安全状态,不过我们在分配资源之前总是要考虑到最坏的情况

    如果系统处于安全状态,就一定不会发生死锁。如果系统进入不安全状态,就可能发生死锁(处于不安全状态未必就是发生了死锁,不过如果没有进程提前释放资源,发生死锁也是将会发生的事情)。

    因此可以在资源分配之前预先判断这次分配是否会导致系统进入不安全状态,以此决定是否答应资源分配请求。这也是银行家算法的核心思想。

允许死锁发生

  • 判断是否发生死锁:资源分配图

    • 定义一种数据结构存储资源的分配情况,实现一种算法检测是否发生死锁;

    • 用一结点表示资源或者进程,进程指向资源的边,表示请求一个该资源,资源指向进程的边表示给该进程分配了多少资源,资源结点的值(通常通过画图表示)表示资源总数量(包括分配出去的资源)。

    • 如果资源分配图的边能被全部简化,说明没有发生死锁,如果不能说明发送了死锁,这个简化的过程其实使用了银行家算法的思想。

  • 解除死锁

    • 资源剥夺法:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但是应防止被挂起的进程长时间得不到资源而饥饿。
    • 撤销进程法(或称终止进程法):强制撤销部分、甚至全部死锁进程,并剥夺这些进程的资源。这种方式的优点是实现简单,但所付出的代价可能会很大。因为有些进程可能已经运行了很长时间,已经接近结束了,一旦被终止可谓功亏一篑,以后还得从头再来。
    • 进程回退法:让一个或多个死锁进程回退到足以避免死锁的地步。这就要求系统要记录进程的历史信息,设置还原点。

饥饿

一个进程长时间无法获得所需资源的状态(比如cpu),可能处于就绪状态也可能处于阻塞状态。

内存管理

内存

内存可存放数据。程序执行前需要先放到内存中才能被CPU处理—缓和CPU与硬盘之间的速度矛盾

装入的三种方式

C语言程序经过编译链接处理后,生成装入模块,即可执行文件,它包含多条指令,可以放入内存中执行。

绝对装入

在编译时,如果知道程序将放到内存中的哪个位置(知道基地址),编译程序将把目标代码中的逻辑地址(相对地址)全部替换成绝对地址(物理地址)装入程序按照装入模块中的地址,将程序和数据装入内存。这种方式的灵活性很差。

简单的来说,使用绝对装入的方式,在将程序编译成可执行文件(装入模块)的时候,就把代码中的逻辑地址转化成了绝对地址,也就是说,装入模块中的地址已经就是绝对地址了。

静态重定位

在装入一个模块到内存的时候,把装入模块中的指令地址数据地址全部转换成绝对地址(物理地址),提高了灵活性,但是如果进程的位置改变了(基地址变了),又会出错。

简单的来说,使用静态重定位的方式,把装入模块放入内存的时候,逻辑地址才会被转化成相对地址

动态重定位

又称动态运行时装入。编译、链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为绝对地址(物理地址),而是把地址转换推迟到程序真正要执行时才进行。因此装入内存后所有的地址依然是逻辑地址(相对地址)。这种方式需要一个重定位寄存器的支持。

采用动态重定位时,运行程序在内存中发生移动。

并且可将程序分配到不连续的存储区中;在程序运行前只需装入它的部分代码即可投入运行,然后在程序运行期间,根据需要动态申请分配内存;便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间。

从写入程序到运行

  • 编译:由编译程序将用户源代码编译成若干个目标模块(编译就是把高级语言翻译为机器语言)
  • 链接:由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块(exe文件)
  • 装入(装载):由装入程序装入模块装入内存运行

内存的分配与回收

连续分配

指的是操作系统为用户进程分配的必须是一个连续的内存空间。

  • 单一连续分配:内存被分为系统区和用户区;系统区通常位于内存的低地址部分,用于存放操作系统相关数据;用户区用于存放用户进程相关数据。内存中只能有一道用户程序,用户程序独占整个用户区空间。

    优点:实现简单;无外部碎片(存在未被分配的空间);可以采用覆盖技术扩充内存;不一定需要采取内存保护。
    缺点:只能用于单用户、单任务的操作系统中;有内部碎片(分配的空间内部还有剩余)存储器利用率极低

  • 固定分区分配:把用户区分为多个大小相等或者不等的区域,每个区域只放一个进程;会存在内部碎片无外部碎片

    操作系统需要建立一个数据结构:分区说明表,来实现各个分区的分配与回收。每个表项对应一个分区,通常按分区大小排列。每个表项包括对应分区的大小、起始地址、状态(是否已分配)

    优点是实现简单,无外部碎片。缺点是当用户程序太大时,可能所有的分区都不能满足需求,此时不得不采用覆盖技术来解决,但这又会降低性能。还可能会产生内部碎片,内存利用率低。

  • 动态分区分配:动态分区分配又称为可变分区分配。这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统分区的大小和数目是可变的

    那系统该使用什么数据结构来记录内存的使用情况呢?常用的两种数据结构是空闲分区表和空闲分区链。

    当很多空闲分区都能满足要求,应该选择哪个分区进行分配?把一个新作业装入内存时,须按照一定的动态分区分配算法,从空闲分
    区表(或空闲分区链)中选出一个分区分配给该作业。由于分配算法算法对系统性能有很大的影响,因此人们对它进行了广泛的研究。

碎片

  • 内部碎片:给进程分配的空间没有被完全利用,常出现在固定分区分配中。
  • 外部碎片:内存中某些空闲分区由于太小而无法被利用(无法分配出去);可以通过紧凑技术解决,但是需要改变进程的基地址,依赖于动态重定位。

离散分配

  • 分页存储

    一个进程可以被划分为多个大小相同的页页号等于逻辑地址/页面大小,页内偏移量等于逻辑地址%页面大小

    内存被分为多个物理块,每个物理块就是一个页框,类似于固定分区分配。

    每个进程都有自己的页表,存储在PCB中,记录了这个进程中所有页面页框的对应关系。

    页表的页号不需要花存储空间存放,可以是隐含的(比如数组的下标就不要被存储),只需要知道页表基地址的大小,可以把页表当作一个数组。块号需要花存储空间存放,存储的只是内存块的编号,不是起始地址。

    那如何进行地址转换呢?

    页表寄存器

    进程页表信息起初存储在进程PCB中,后续调用的时候把页表基地址长度存储在页表寄存器中,但是页表其他信息还是存储在内存中。

  • 分段存储

    划分进程空间的时候是按逻辑划分的,划分为一个一个段;分页对用户是不可见的,分段是可见的,需要指定的

  • 段页式存储

    把进程按逻辑划分为段,但是存储的时候又把每个段划分为页(先分段再分页),每个段对应一个页表,段表存储的则是每个段的页表的位置和页表大小。

虚拟内存

是什么

传统存储管理,包括前面介绍的连续分配非连续分配,有许多特征,缺点。

  • 一次性:作业必须一次性全部装入内存后才能开始运行。这会造成两个问题:
    • 作业很大时,不能全部装入内存,导致大作业无法运行
    • 当大量作业要求运行时,由于内存无法容纳所有作业,因此只有少量作业能运行,导致多道程序并发度下降
  • 驻留性:一旦作业被装入内存,就会一直驻留在内存中,直至作业运行结束。事实上,在一个时间段内,只需要访问作业的一小部分数据即可正常运行,这就导致了内存中会驻留大量的、暂时用不到的数据,浪费了宝贵的内存资源。

其实这些问题都可以使用虚拟存储技术解决。

虚拟存储技术基于局部性原理

  • 时间局部性:如果执行了程序中的某条指令,那么不久后这条指令很有可能再次执行;如果某个数据被访问过,不久之后该数据很可能再次被访问,因为程序中存在大量的循环。
  • 空间局部性:一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问,因为很多数据在内存中都是连续存放的,并且程序的指令也是顺序地在内存中存放的。

基于局部性原理,在程序装入时,可以将程序中很快会用到的部分装入内存,暂时用不到的部分留在外存,就可以让程序开始执行

在程序执行过程中,当所访问的信息不在内存时,由操作系统负责将所需信息从外存调入内存,然后继续执行程序。
若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。

操作系统的管理下,在用户看来,似乎有一个比实际内存大得多的内存,这就是虚拟内存

特征

  • 多次性:无需在作业运行时一次性全部装入内存,而是允许被分成多次调入内存,按需调入内存。
  • 对换性:在作业运行时无需一直常驻内存,而是允许在作业运行过程中,将作业换入、换出。
  • 虚拟性:从逻辑上扩充了内存的容量,使用户看到的内存容量,远大于实际的容量。

如何实现

内存分类

ROM

ROM(read only memory),只读存储器,即:它只能读出信息,不能写入信息,计算机关闭电源后其内的信息仍旧保存,一般用它存储固定的系统软件字库等。

BIOS(basic iput/output system)

它提供了硬件初始化加载操作系统的功能,存储在ROM中;操作系统本身是存储在计算机的外存设备上的,如硬盘或SSD(固态硬盘,Solid State Drive,操作系统通常安装在SSD的C盘上),并在计算机启动时被加载到内存中运行

RAM

RAM,全称为随机存取存储器(Random Access Memory),

是计算机系统中的一种主要存储器类型。它用于临时存储正在运行的程序和数据,以便处理器能够快速访问。RAM的特点是可以被迅速读写,并且支持对任何存储位置的随机访问,即访问时间与存储位置无关

主要特性

  • 易失性:RAM是一种易失性存储器,意味着当电源关闭时,存储在其中的数据会被清除。因此,它主要用于存储那些需要频繁修改和访问的数据。
  • 高速度:相比硬盘驱动器或固态硬盘等永久存储设备,RAM提供了更快的数据读写速度,这使得它非常适合用于作为CPU的主存储区域,以加快计算任务的处理速度。
  • 容量与成本:随着技术的进步,RAM的容量不断增大,同时单位价格也在下降。不过,相较于其他类型的存储介质,相同容量下的RAM通常更昂贵。

拓展:外存

硬盘属于外存,是可读写的,且永久保存,比如C盘,D盘。

I/O

I/O设备

I/O设备就是可以将数据输入到计算机,或者可以接收计算机输出数据的外部设备,属于计算机中的硬件部件。UNIX系统将外部设备抽象为一种特殊的文件,用户可以使用与文件操作相同的方式对外部设备进行操作。要注意的是,网络通信设备也属于io设备。

I/O控制器

cpui/o电子部件的中间设备,位于电脑上而不是IO设备上

IO控制器的组成包括:多种寄存器,I/O逻辑,控制器与设备的接口。

IO控制器的核心是IO逻辑

I/O控制方式

程序直接控制

需要cpu轮询检查i/o设备状态,此时不能做其他事情,i/o和cpu处理只能串行

中断驱动

引入中断机制。由于I/O设备速度很慢,因此在CPU发出读/写命令后,可将等待I/O的进程阻塞,先切换到别的进程执行[进程:我需要IO操作,CPU:我帮你向控制器发命令了,你先下CPU吧,我去忙别的]。当I/O完成后,控制器会向CPU发出一个中断信号[控制器:IO操作完毕,CPU大人快来取数据吧],CPU检测到中断信号后,会保存当前进程的运行环境信息,转去执行中断处理程序处理该中断[CPU:别急,等我保存我的工作记录,再来取数据]。处理中断的过程中,CPU从I/O控制器读一个字的数据传送到CPU寄存器,再写入主存。接着,CPU恢复等待I/O的进程(或其他进程)的运行环境,然后继续执行[CPU:你需要的IO操作完成了,我要继续完成你这个进程了]

注意

  • CPU会在每个指令周期的末尾检查中断
  • 中断处理过程中需要保存、恢复进程的运行环境这个过程是需要一定时间开销的。可见,如果中断发生的频率太高,也会降低系统性能。
  • 每次中断只能读入一个字,如果需要读入大量数据,就需要多次中断。

DMA

DMA方式(Direct MemoryAccess,直接存储器存取),数据传输的过程不需要经过cpu(不需要通过cpu寄存器写入内存),一次cpu命令能读取一块或者多块连续内存,写入到内存不需要经过cpu,由DMA直接写入。当DMA传输完成后,DMA控制器会通过中断的方式通知CPU数据传输已经完成,以便CPU可以进行后续处理。

通道

只能用来处理io的处理机,相当于阉割版的cpu,通道没有自己的内存,通道程序(cpu给的任务清单)存储在内存中,通道需要读取内存中的通道程序并运行;引入通道的目的是让数据的传输独立于CPU,使CPU从繁重的I/O工作中解脱出来。

假脱机技术

也叫spooling技术,用软件的方式模拟脱机技术(脱离主机控制进行输入输出操作,把cpu从繁重的io工作中解放出来)。可以把物理设备虚拟为多个逻辑设备,比如,使用spooling技术改造打印机,对于进程使用打印机的请求,把它放入打印任务队列中,让进程以为获得了打印机设备

I/O操作大致过程

用户程序→系统调用处理程序→中断处理程序→设备驱动程序

当一个用户程序需要执行I/O操作(如读写文件、网络通信等)时,它不能直接访问硬件资源。因此,程序会通过系统调用请求操作系统的服务。系统调用是一种特殊的接口,它允许用户空间的应用程序请求内核提供的服务。当用户程序发出系统调用时,CPU会从用户态切换到内核态,即发生了中断。中断处理程序将 I/O 请求传递给相应的设备驱动程序,设备驱动程序运行在内核态,因为需要直接访问硬件资源。