第一章OS基本概念
1.1os概念、功能和目标
用QQ和朋友聊天的过程:
- 逐层打开文件夹,找到exe存放位置
- 将程序相关数据放入内存
- 运行程序,对应进程被处理机处理
- 将硬件设备分配给进程
命令结构允许用户直接使用,程序接口允许用户通过程序间接使用。
通常将提供的功能成为用户接口
1.1.1用户接口
1.1.2命令接口
- 联机命令接口实例(交互式)
- 脱机命令接口实例(批处理)
1.1.3程序接口
回顾
1.2OS的四个特征
1.2.1并发
1.2.2共享
- 分为互斥和同时共享
- 互斥共享:如使用qq和微信进行视频,摄像头一段时间只能分配给一个进程使用
- 同时共享:使用qq和微信发送文件。宏观上两个同时发送(访问硬盘),微观上两个交替发送(访问硬盘)
1.2.3并发和共享的关系
- 并发性和共享性互为存在条件。
1.2.4虚拟
- 上面提到了空分复用技术和时分复用技术
1.2.5异步性
1.3OS的分类与发展
- 手工操作阶段:如打孔式计算机。输入输出慢,处理快,cpu有大量时间等待输入输出
- 批处理
- 单道批处理:引入脱机输入输出技术(用外围机将纸带数据读取到磁带完成),缓解了一定速度矛盾。但是计算机内存同时只能读取一个程序,大量时间在等待IO完成。
- 多道批处理:每次往内存中输入多道,OS来管理程序的运行,使程序并发执行,提升了资源的利用效率。但是没有提供人机交互的能力。
- 分时操作系统:以时间片为单位轮流为用户提供服务,解决了人机用户的交互问题。缺点是不能解决优先处理紧急任务
- 实时操作系统:解决了优先解决紧急任务,某些紧急任务无需分配时间片。
为什么说多道批处理提升了CPU资源的效率?
实时操作系统的分类
other
1.4OS运行机制与体系结构
1.4.1运行机制
两种指令
高级语言将会翻译为多条机器语言指令。
两种处理器状态
两种程序
有的程序能够执行特权指令,有的只能执行非特权指令
1.4.2系统内核
1.4.3体系结构
- 内核可以分为大内核和微内核两种
1.5中断和异常
应用程序的输入设备和处理设备速度不匹配,如:打字需要的时间远远多于cpu处理的时间,大量。那么我们就思考可不可以在输入没完成的时间cpu去执行其他任务,为了解决这个问题,出现了中断。
当受到中断信号,cpu由用户态切换到核心态。cpu权限交给操作系统,操作系统负责对中断信号进行处理。
完成后将cpu使用权交还给用户进程。进程2执行一段时间后可能会发出系统调用(内中断信号),请求输出。
cpu切换为核心态,对中断进行处理。。。。。。。
- 中断发生,cpu立即进入核心态
- 中断发生,运行的进程暂停,并由os内核对中断进行处理。
- 不同中断的中断信号,会进行不同的处理。
操作系统的管理工作需要用到特权指令,因此cpu需要转换为核心态,中断可以使CPU从用户态切换为核心态,使得操作系统获得计算机的控制权。
1.5.1中断的分类
如打印机完成后的中断就是外中断。
1.5.2外中断的处理过程
1.6系统调用
1.6.1概念,作用
- 概念
系统调用是操作系统提供给应用程序使用的接口,可以理解为一种可供程序调用的特殊函数,应用程序可以发出系统调用请求来获得操作系统的服务。 - 作用
1.6.2系统调用和库函数的区别
- 注意有的库函数涉及系统调用,而有的库函数并不涉及系统调用。
1.6.3系统调用背后的过程
多种系统调用操作系统怎么分辨具体需要运行哪一个呢?通过int指令的参数。
第二、处理机管理
2.1 进程定义、组成、组织及特征
2.1.1定义
- 单道程序内存中同一时间段内只允许执行1个应用程序。
- 多道程序内存中可以存在多个应用程序
进程实体由程序段、数据段、PCB三部分组成 - 程序段用来存放程序
- 数据段用来使用和产生数据
- PCB用来管理进程
2.1.2组成
进程的组成
PCB的组成
- 进程描述信息
- 进程识别符PID
- 用户标识符UID
- 进程控制和管理信息
- 进程状态
- 进程优先级
- 资源分配清单(程序段、数据段指针、键鼠)
- 处理机相关信息(各种寄存器值)
2.1.3进程的组织
- 连接方式
- 根据状态将PCB分为多个队列
- OS持有指向各个队列的指针(分别有就绪态队列指针和阻塞态队列指针)
- 索引方式
- 根据进程状态不同建立几张索引表
- OS持有指向各个索引表的指针(分别有就绪态表指针和阻塞态表指针)
2.1.4进程的特征
进程与程序的区别:
- 进程是动态的,程序是静态的
- 进程有一定生命周期,程序只是指令的集合
2.2 进程状态的状态与转换
2.2.1进程的状态
正常运行的基本状态
- 单核处理机环境下,同一时刻最多只有一个进程处于运行态
- 处理态拥有除了处理机之外所有需要的资源。
另外两种状态
- 创建态
- 终止态
阻塞态只能先转换为就绪态才能转换为阻塞态
运行->阻塞是一种 OS主动行为
阻塞->就绪是一种被动行为
2.2.2进程的控制
进程的控制是通过进程控制相关的原语实现的。
原语的功能
2.3进程通信
什么是进程通信?
2.3.1共享存储
2.3.2管道通信
管道只能实现半双工通信,若要实现双向同时通信,需要设置两个管道
半双工通信 没写满不准读、没读空不许写 读进程最多只有一个
2.2.3消息队列
两种方式:
- 直接通信方式:直接挂在缓冲队列上
- 间接通信方式:借助中间实体(信箱)
2.2.4套接字、信号量、信号
2.4 线程的概念和多线程模型
线程概念
线程是一个基本的cpu执行单元,也是程序执行流的最小单位。
进程只作为除了CPU之外的系统资源的分配单元。
带来的变化:
线程的属性
注意:
同一个进程的线程共享进程的资源
由于同一进程的线程共享内存地址空间,所以他们之间的通信无需系统干预。
同一进程线程的切换开销较小,不同进程之间线程的切换开销较大。
线程的实现方式
- 用户级线程
- 内核级线程
- 二者混合
多线程模型
多对一模型:
优点:线程之间的切换在用户态即可完成,开销小、效率高。
缺点:当一个用户线程受阻塞时,整个进程都会被阻塞。多个线程不可在多个cpu上并发执行。
一对一模型:
优点:并发能力强
缺点:线程的切换开销更大、效率更低
多对多模型:
集二者之长。
2.5 处理机调度
基本概念
处理机调度:由于进程数往往多于核数,从就绪队列中按照一定算法选择一个进程并将处理机分配给它运行,已实现程序并发执行。
调度的三个层次
- 高级调度(作业调度)
调入时间由操作系统决定,调出时间由作业运行结束决定。 - 中级调度(内存调度)
虚拟存储技术将暂时不可运行的程序调入外存等待。等之具备运行条件,内存又有空闲时再重新调入内存(这个过程就是中级调度)。
调入外存后等待的状态称之为挂起状态,注意挂起的PCB不会调往外存。
五状态模型的扩展:
- 低级调度(进程调度)
用于从就绪队列中选取一个进程,将处理机分配给它。
进程调度的时机、切换与过程、方式
进程调度就是之前说的低级调度。
-
时机
注意倒数第二条说的时内核程序临界区 -
调度方式
-
进程的切换和过程
对原来进程的数据的保存
对新的进程的各种数据的恢复
进程的切换越频繁反而效率更低
2.6调度算法
评价算法的指标
- cpu利用率
- 系统吞吐量
- 周转时间
在周转时间相同的情况下。对于运行时间不同的作业,给用户的感觉肯定是不同的。因此引入带权周转时间。 - 等待时间
作业处于等待处理机状态时间之和。
- 响应时间
FCFS(先来先服务)、SJF(短作业优先)、HRRF(高响应比优先)
- 先来先服务
- 短作业优先
- 高响应比优先
- 三种算法的对比
时间片轮转调度、优先级调度、多级反馈队列调度
- 时间片轮转调度
- 优先级调度
- 多级反馈队列调度
这三种算法比较适合交互式系统。
2.7进程同步与互斥的实现
2.7.1进程互斥的软、硬件实现方式
进程同步:由于进程具有异步性的特征,各并发执行的进程以各自独立的不可预知的速度推进。而有时我们需要进程之间按照一定的顺序(如进程通信中的管道通信,先写后读),所以需要进程异步。
进程互斥:各进程不可避免的需要共享一些系统资源。互斥资源(一段时间只允许一个进程使用的资源)的访问,必须互斥的进行。
进程互斥的软件实现方法
- 单标志法
缺点:若进程0允许访问临界区,而它又不访问,那么就会一致卡在这里 - 双标志检查
由于进程的异步性,有可能代码并不按顺序执行导致两进程同时访问临界区。违反了“忙则等待”的原则,进入区的检查和上锁不是同时完成的。 - 双标志后检查
- Perterson算法
通俗的理解:
缺点:仅仅遵守了空闲让进、忙则等待、有限等待三个原则。没有遵守让权等待原则(即进程不能进入临界区的时候,立即放弃处理机)
进程互斥的硬件实现方法
- 中断屏蔽方法
关中断后不允许当前进程被中断,也必然不会引发进程切换。直到进程访问玩完临界区后在开中断指令执行。才能允许其他进程上处理机并访问临界区。
优点:简单、高效。
缺点:不适用于多处理机的系统:只适用于操作系统内核进程,不适用于用户进程(因为开关中断指令只能运行在内核态)
- TestAndSet指令。
- swap指令
注意,这里硬件实现中的检查和上锁是同步实现的。
2.7.2信号量机制
之前介绍的软硬件实现方式或多或少都存在弊端,无法实现让权等待,也就是进程不能进入临界区时应该释放处理机
信号量其实是一个变量,用于表示系统中某种资源的数量(分为整型和记录型两种)。
可以使用一组原语wait(s)和signal(s)来实现。
整型信号量
OS对信号量的操作有:初始化、P、V操作
之前提到的软硬件实现方式都存在或多或少的问题。
wait那里检查和上锁一气呵成,避免了并发、异步导致的问题。
缺点:不满足让步等待原则,如果某个进程进入不了临界区,会一直卡在这里,发生忙等现象。
记录型信号量(常用)
所以P2进程会被挂到打印机队列里,S.value的值就是等待的线程的个数。
信号量机制完成进程互斥、同步、前驱关系
- 互斥
- 同步
如下代码要求代码4在代码12完成之后执行。
设置初始量为0,前代码末V后代码初P - 前驱
2.7.3经典问题
生产者-消费者问题
缓冲区满了,就需要消费者取走后才能进入缓冲区。缓冲区是临界资源,各进程必须互斥的访问。
互斥的访问同一个缓冲区、同步的访问空闲缓冲区和非空闲缓冲区的数量。
对mutex的PV操作是为了解决互斥问题、对full的的PV操作是为了解决对产品数量的同步、对empty的PV操作是为了解决对空闲缓冲区数量的同步关系。
思考:能否改变消费者、生产者里的两个P的顺序呢?
当消费者互换P顺序时:
多生产者-多消费者问题
存在多个生产者和多个消费者,且可能不同生产者生产的东西、消费者消费的东西不是一样的。
- 1.分析同步、互斥关系
- 2.整理思路、确定P、V操作
互斥:在临界区前后分别PV
同步:前末V后首P - 3.设置信号量
对于互斥的初始值设置为1,同步信号需要看资源的初始值。
吸烟者问题
- 分析关系
- 整理思路
- 设置信号量
最终结果:
读者-写者问题
多个读者写者线程共享一个文件,文件由一系列的记录组成。如果读进程在读数据,而写进程将数据修改了,读进程本来想去读原来的数据的,但是由于修改读取到的是后面改完的数据。
所以做出要求:允许多个同时读取、允许一个写、任意写者没完成前不许其他读和写、写着执行前,应该让已有的读者、写者退出
- 分析关系
写进程和写进程之间存在互斥、写进程和读进程互斥(写的时候不能有其他读写)。读进程之间不存在互斥。 - 整理思路
设置互斥信号量rw。在写者访问文件前后P、V。(解决写者和其他互斥的问题)
读者、写者间互斥。所以读者访问文件前后也要对rw进行P、V。
但是这样怎么解决两个进程同时访问文件呢?
但是这样当两个进程同时读取时:
可以设置一个互斥变量解决检查和赋值无法一气呵成。
但是这样的话,如果读进程源源不断的到来,写进程一直阻塞,可能“饿死”。
解决方法:设置一个新的互斥信号量分别对其执行P、V,以实现写优先。
哲学家进餐问题
当直接对左右筷子进行P、V以实现互斥时:
没个进程在占有了一份临界资源的情况下进入阻塞。怎么解决呢?
以3为解决方案。
2.7.4管程
- 管程的组成结构
- 管程的特征
翻译为人话:
该数据结构只能被管程内部的过程访问,同一时间只能执行一个管程内的过程。
使用管程解决生产者消费者问题
java中类似管程的机制
2.8死锁的处理
死锁的概念
- 死锁、饥饿、死循环的区别
- 死锁发生的条件
当同类资源只有一个,那么循环等待就是死锁的充分必要条件。
处理
处理——预防
- 破坏互斥条件(即对资源的争抢)
但是并不是所有设备都可以改造未共享设备,且有时处于安全考虑不能这样做。 - 破坏不剥夺条件(资源只能自己释放)
- 破坏请求和保持条件
- 破坏循环等待条件
处理——避免死锁
安全与不安全
安全状态一定不会死锁,不安全状态就可能发生死锁。
- 银行家算法
第一步检查进程的资源申请是否超过之前承诺的最大申请量,没超过进入第二步,否则出错。
第二部判断系统剩余资源是否满足资源申请数量,满足转向3,否则阻塞。
第三步试探着分配资源给进程,并修改相应的数据(注意,不是真的分配,只是为了预判)
第四步检查系统 是否处于安全装填状态。
处理——检测和解除
系统应提供两种算法:检测算法,用于检测系统的状态,以确定系统是否发生死锁;死锁解除算法:当认定系统中已经发生了死锁,可用该算法将系统从死锁状态中解除。
定义蓝色圆块为进程节点,绿色方块为资源节点(里面的圆块数就是资源的数量),蓝色边为进程->资源,表示进程想申请几个资源,绿色边为资源->进程,表示给进程分配了几个资源。
检测死锁的算法:
解除死锁的算法:
可以根据进程优先级、执行时间、还要多久、已经使用了多少资源、进程是交互式的还是批处理式的
第三章、内存管理
3.1内存基础及内存管理
什么是内存?
- 内存管理
3.2内存分配和回收
连续分配管理
- 单一连续分配
- 固定分区分配
- 动态分区分配
3.
动态分区分配算法
之前提到过当多个分区满足空闲要求时,应当选择哪个分区进行分配
非连续分配管理
分页存储管理
基本分段管理
- 基本分页和基本分段的区别
段页式管理方式
- 基本概念
- 逻辑地址结构
- 段表、页表
一个进程仅一个段表,而可以有多个页表
3.3内存空间的扩充
3.3.1覆盖与交换
- 覆盖与交换
3.3.2虚拟存储技术
传统存储方式的缺点
传统的存储方案(连续分配、非连续分配)导致暂时用不到的数据也会长期占用内存,导致内存利用效率不高。:
- 一次性
- 驻留性
因此提出虚拟存储技术,该技术主要基于局部性原理:
局部性原理
虚拟内存有以下三个特征:
- 多次性:无需在作业运行时将之一次性调入内存,而是允许被分成多次调入内存中。
- 对换性:作业运行时无需一直常驻内存,而是允许在作业运行过程中,将作业换入换出。
- 虚拟性:逻辑上扩容了内存。
如何实现虚拟内存技术:?
请求分页式存储管理
- 分页机制的区别
- 为了实现请求调页功能,新增缺页中断机构
- 地址变换的区别
页面置换算法与页面分配策略
- 页面置换算法
最佳置换算法:
017中7是最后一个且长时间不会被访问的,因此淘汰7号页面。
整个过程中缺页中断发生了9次,页面置换发生了6次。
先进先出置换:
3先进入,所以淘汰3号页面。
缺点:存在贝拉迪异常
最近最久未使用置换算法:
每次淘汰得页面是最近最久得未使用的页面。
7号页面就是最近最久没有被使用到得页面。因此淘汰它。
时钟置换算法:
- 页面分配策略
- 何时调入页面
- 何处调入页面
- 抖动现象
- 工作集
第四章、文件管理
4.1初识文件属性
文件的属性
文件名:方便用户找到文件,同一目录下不允许有重名文件
标识符:一系统内标识符号唯一,只是操作系统用于区分各个文件的一种内部名称。
类型:指明文件类型的属性
位置:文件存放的路径
保护信息:可不可读等等。
大小、创建时间、文件所有者信息等等
文件内部的数据应该怎样组织
文件分为有结构文件和无结构文件
文件之间应该怎样组织
操作系统应该向上提供哪些功能
- 创建文件功能
- 读文件的功能
- 写文件的功能
- 删除文件的功能
- 打开、关闭文件的功能
文件如何存放
之后文件的物理结构会介绍文件应该连续放在几个块中还是离散的放在几个块中
其他功能
文件共享:多个用户可以共享使用一个文件
文件保护:保证不同用户对文件有不同操作权限
4.2文件的逻辑结构
指的就是用户看来文件内部的数据应该怎么组织起来。物理结构是指操作系统看来,文件如何存在在外存中。
按照结构分,文件可以分为无结构文件和有结构文件:
-
顺序文件
-
索引文件
适用于对信息处理及时性要求比较高的场合
-
索引顺序文件
将记录文组,分组都为顺序文件
从上图可以认为索引顺序文件可以认为是定长记录的串结构的顺序文件。
检索效率分析:
但是如果记录数太多,分组也多,查询的次数还是 特别多,可以建立多级索引:
4.3文件目录
文件控制块
目录中的一条记录就是一个文件控制块,其中包含了文件基本信息(文件名、物理地址、逻辑物理结构等等),存储控制信息,使用信息等,其中最重要的就是文件名、文件存放的物理地址。
目录结构
- 单极目录
- 两极目录结构
分为主文件目录和用户文件目录,分别是用户名及用户目录存放位置和用户文件的FCB组成。
缺点:不能将文件分类 - 多级目录结构
引入相对路径和当前目录后,磁盘IO减少了,提升了访问文件的效率。
缺点:树形结构不便于实现文件的共享。 - 无环图目录结构
加入共享节点,可以由不同的文件名指向同一个文件。
注意:共享文件指向的是同一份文件
索引节点
- 什么是索引节点
其实只有在查找各级目录的过程中,只需要用到文件名这个信息,所以对之前的FCB进行简化
4.4文件的物理结构
主要探讨的是对非空闲磁盘块的管理,也就是存放了文件数据的磁盘块。
类似于内存分页,磁盘的存储单元也会分为也会分为一个个块。很多OS中,磁盘块的大小与内存块、页面的大小相同。因为内存和磁盘间的内存交换都是以块为单位的
操作系统需要将逻辑块号和块内地址转换为物理地址。
连续分配
顺序访问:想要访问到逻辑块号2,必须从0开始访问到2
直接访问:可以直接找到逻辑块号2
缺点是拓展不方便,存储效率低,会产生难以利用的磁盘碎片。
链接分配
隐式链接:
显式分配:
如何实现逻辑块号->物理块号?
支持顺序访问,也支持随机访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6wEHFdYV-1672165591662)(https://imgzblog.csdnimg.cn/45ade6a6caba4e65bce48046b54b793b.png)]
索引分配
-
索引分配
每个索引表存放有指向下一个索引表的指针
-
多级索引
缺点:加入一个文件只有1kb这样大小的物理块,如果使用两层索引,仍然需要三次读磁盘。 -
混合索引
4.5文件存储空间管理
主要探讨空闲磁盘块的管理
4.5.1存储空间的划分与初始化
安装操作系统时为磁盘分区,就是将物理磁盘划分为一个个文件卷(逻辑卷、逻辑盘)
每个文件卷包括目录区和文件区两部分。
目录区主要存放FCB、用于磁盘存储空间管理的信息;文件区主要用来存放普通的文件数据
4.5.2几种管理方法
空闲表法
用一个空闲表记录空闲区间的起始块号和长度。适用于连续分配方式
空闲链表法
- 区别
>空闲盘块链
OS中保存着链头、链尾指针
>空闲盘区链
OS同样保存链头、链尾的指针。
位示图法
分配:
成组链接法
要求保证内外存超级块数据一致。
如何分配?
4.6文件的基本操作
- 创建
- 删除
- 打开
注意区分进程的打开文件表和系统的打开文件表:
我们平常在删除正在打开的文件的时候,往往会提示正在打开,无法删除。这是因为删除时会去检查系统的打开文件表的打开计数器,查看是否已经打开。
进程的打开文件表有读写指针和访问权限两个特殊字段。
-关闭
- 读
- 写
4.7文件共享
- 硬链接(基于索引节点)
- 软链接(基于共享方式)
当user1user2不再需要文件1,所以count=0,文件1被删除;此时user3访问文件2link的文件,会发现文件已经删除,无法找到文件1。
4.8文件保护
- 口令保护
- 加密保护
优点:保密性强,无需再系统存储密码
缺点:编码和译码需要时间 - 访问控制
4.9文件系统的层次结构
4.10磁盘结构
磁盘的分类:
根据磁头是否可以移动分为:活动头磁盘和固定头磁盘,固定头磁盘每个磁道每个盘面都有磁头,读取时激活对应的磁头即可
根据盘片是否可以更换分为:可换盘磁盘和固定盘磁盘
4.11磁盘调度算法
一次读写耗时
延迟时间与磁盘转速线性相关,转速是硬盘固有的属性OS无法更改,所以OS唯一可以影响的就是寻找时间。
各种算法
- 先来先服务
- 最短处理时间
- 扫描算法
- LOOK调度算法
- C-SCAN算法
- C-LOOK算法
4.12减少延迟时间的方法
如果逻辑上相邻的扇区让他物理也相邻,需要转好几圈才能将信息读取,因为读完一个扇区需要时间处理。
解决方法:
- 交替编号
理解下 磁盘地址物理结构的设计
- 错位命名
4.13磁盘的管理
- 磁盘初始化
一个扇区分为头、尾(之前讲的链式存储的指针存放在尾部)、数据区域
- 引导块
因为rom只读,无法更新,所以现在的操作系统会在ROM只装一个自举装入程序,完整的自举程序放在磁盘的**启动块(即引导块/启动分区)**上,启动块位于磁盘的固定位置。
拥有启动块的磁盘称为启动磁盘/系统磁盘。 - 坏块的管理
五、设备管理
5.1IO设备概念及分类
输入:如鼠标、键盘
输出:如显示器
输入输出:如移动硬盘
5.1.1分类:
按照使用特性分类:
人机交互类、存储类、网络通信类
按照传输速率分类:
低速、中速、高速
按照信息交换单位分类:
块设备、字符设备
5.1.2 I/O控制器
- IO控制器的组成
控制线用于选择哪个io设备、地址线用于访问对应地址,数据寄存器钟存放数据、控制寄存器存放参状态寄存器存放io设备状态。
5.2IO控制方式
5.2.1程序直接控制方式
5.2.2中断驱动方式
5.2.3DMA方式
5.2.4通道控制方式
5.3IO软件层次结构
5.3.1用户层软件
用户层软件通过OS提供的系统调用来与请求操作系统内核的服务。
5.3.2设备独立性软件
功能1:提供系统调用
功能2:提供设备的保护
功能3:差错处理
功能4:设备的分配与回收
功能5:数据缓冲区管理
功能6:建立逻辑设备名到物理设备名的映射;根据设备类型调用相应的驱动程序。
方式1:整个OS设置一张逻辑设备表;方式2:为每个用户设置1张逻辑设备表
5.3.3设备驱动程序
5.3.4中断处理程序
5.4IO核心子系统
就是上节的中间三层实现的功能:
假脱机技术
-
脱机技术原理及问题
早期打纸带处理快,读取慢:
于是引入脱机输入/输出技术:
-
假脱机技术原理
I/O调度
设备保护
5.5设备的分配与回收
设备分配时应考虑的因素
- 固有属性
- 设备分配算法
- 设备分配的安全性
静态分配与动态分配
设备管理中需要用到的数据结构
设备分配的步骤
- 根据设备物理名查系统设备表
- 根据系统设备表找到对应的设备控制表,若设备忙则挂起到等待队列,空闲则将之分配给进程
- 根据设备控制表找控制器控制表,不忙则将控制器分给进程,否则挂起到等待队列
- 根据控制器控制表找到通道控制表…
改进的分配步骤
5.6缓冲区管理
单缓冲
所以单缓冲平均耗时:max(C,T)+M
双缓冲
综上,平均耗时max(T,C+M).