电子科技大学操作系统期末复习

操作系统复习电子科技大学(前三章图片丢失)

image-20230612130500653

image-20230612130508678

image-20230616161533913

image-20230616161555482

第一章

1.单道批处理系统

  • 主要特征;

    • 自动型
    • 顺序性
    • 单道性
  • 优点:

    • 减少人工操作,解决了作业的自动接续
  • 主要缺点:

    • 平均周转时间长,没有交互能力

2.多道批处理系统

  • 主要特征:

    • 多道性
    • 无序性
    • 调度性
  • 好处:

    • 提高CPU利用率
    • 提高内存和I/O设备利用率
    • 增加系统吞吐率
  • 优点:

    • 提高了资源利用率和吞吐能力
  • 缺点:

    • 平均周转时间长,没有交互能力。
  • 多道批程序需要解决的五个问题:

    • 处理机管理:分配和控制CPU
    • 存储器管理:内存分配与回收
    • I/O设备管理:I/O设备的分配与操纵
    • 文件管理:文件的存取、共享和保护
    • 作业的管理:如何组织作业运行

3.分时操作系统

  • 特点:
    • 多路性:一个主机与多个终端相连
    • 独立性:彼此独立操作,互不干扰
    • 及时性:系统能在很短的时间得到回答
    • 交互性:能实现人机对话(区别于批处理系统

4.实时系统

  • 所谓实时系统:是计算机及时响应外部事件的请求, 在规定的时间内完成对该事件的处理,并控制所有实时设备和实时任务协调一致的运行

1、实时控制系统:工业控制,军事控制,医疗控制,…….

2、实时信息处理系统:航班定票,联机情报检索,……

  • 特征:
    • 多路性:能对多个对象进行控制
    • 独立性:独立运行,不混淆,不破坏
    • 交互性:仅限于访问系统中某些特定的专用服务程序
    • 可靠性:高可靠性,应具有多级容错防护能力
    • 及时性:不同的系统要求不一样,控制对象必须在截止时间内完成

二、操作系统基本特征

  • 四个基本特征
    • 并发性(最重要)
    • 共享性
    • 虚拟性
    • 异步性
    • 并发是最重要的特征,其它特征都以并发为前提。

1.并发

    1. 并发——并行性和并发性,并发执行的过程。

      ▪ - 并行性:是指两个或多个事件在同一时刻发生。

      ▪ - 并发性:是指两个或多个事件在同一时间间隔内发生。

      ▪ 任务共行 - 从宏观上看,任务共行是指系统中有多个任务同时运行 - 从微观上看,任务共行是指单处理机系统中的任务并发 (Task Concurrency:即多个任务在单个处理机上交替 运行)或多处理机系统中的任务并行(Task Parallelism: 即多个任务在多个处理机上同时运行)

  • 进程是资源分配的基本单位

  • 线程是独立运行和调度的基本单位

2.共享

  • 指操作系统中的资源可供内存中多个并发执行的进程共同使用
临界资源
  • 把在一段时间内只允许一个进程访问的资源,称为临界资源。如打印机、栈、表格等

  • 互斥共享方式

    • 系统中的临界资源可以提供给多个进程使用,但一段时间内仅允许一个进程使用,称为互斥共享方式。
  • 同时访问方式

    • 宏观上看,资源共享是指多个任务可以同时使用系统中的软硬件资源。
    • 微观上看,多个进程交替互斥地使用系统的某个资源。例如磁盘。
  • 并发和共享是操作系统的两个最基本的特征,它们又是互为存在的条件

3.虚拟

  • 指通过某种技术把一个物理实体变为(映射为) 若干个逻辑上的对应物
  • 时分复用技术
    • 虚拟处理机:分时实现
    • 虚拟设备:SPOOLING技术
  • 空分复用技术
    • 虚拟磁盘技术:逻辑分区
    • 虚拟存储器:虚拟存储管理实现

4.异步性

  • 执行结果不确定,程序不可再现
  • 多道程序环境下程序(进程)以异步的方式执行,每道程序在何时执行、各自执行的 顺序、完成时间都是不确定的,也是不可预知的。

三、操作系统的主要功能

五大功能
  • 处理机管理(CPU)
  • 存储器管理
  • 设备管理
  • 文件管理
  • 方便用户使用的用户接口
无结构操作系统
  • 缺陷:
    • 设计出的操作系统既庞大又杂乱,缺乏清晰的程序结构
    • 编制出的程序错误很多,给调试工作带来很多困难;增加了维护人员的负担。
模块化OS结构
  • 使用分块结构的系统包含若干module(模块);其中, 每一块实现一组基本概念以及与其相关的基本属性

  • 块与块之间的相互关系:

    • 所有各块的实现均可以任意引用其它各块所提供的概念及属性。
  • 优点:

    • 提高了OS设计的正确性、可理解性和可维护性
    • 增强了OS的可适应性。
    • 加速了OS的开发过程。
  • 缺点:

    • 对模块的划分及对接口的规定要精确描述很困难。
    • 从功能观点来划分模块时,未能将共享资源和独占资源 加以区别。
分层式OS结构
  • 使用分层系统结构包含若干layer(层);其中,每一层 实现一组基本概念以及与其相关的基本属性

  • 层与层之间的相互关系:

    • 所有各层的实现不依赖其以上各层所提供的概念及其 属性,只依赖其直接下层所提供的概念及属性
    • 每一层均对其上各层隐藏其下各层的存在
  • 考虑因素
    *

操作系统层次化体系结构

2.进程

  • 进程的定义:
    • 是程序的一次执行
    • 是一个程序及其数据在处理机上顺序执行所发生的的活动
    • 进程是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位
  • 特征
    • 结构特征
      • 程序段、相关的数据段和PCB三部分便构成了进程实体。
      • 谓创建进程,实质上是创建进程实体中的PCB; 而撤消进程,实质上是撤消进程的PCB。
    • 动态性:
      • 进程的实质是进程实体的一次执行过程,因此,动态性是进程的最基本的特征。
      • 动态性表现:“它由创建而产生,由调度而执行,由撤消而消亡”。具有一定生命周期
      • 程序是一组有序指令的集合,其本身并不具有运动的 含义,因而是静态的
    • 并发性:
      • 这是指多个进程实体同存于内存中,且能在一段时间内同时运行。
    • 独立性:
      • 指进程实体是一个能独立运行、独立分配资源和独立接受调度的基本单位
    • 异步性:
      • 指进程按各自独立的、不可预知的速度向前推进,或说进程实体按异步方式运行
进程和程序的主要区别
  • 程序是指令的有序集合,是静态的;进程是程序在处理机上的一次执行过程,是动态的

  • 程序的存在是永久的;而进程是有生命周期的,它因创建而产生,因调度而执行,因得不到资源而暂停执行,因撤消而消亡。

  • 程序仅是指令的有序集合;而进程则是由程序段、数据段、PCB组成

  • 进程与程序之间不是一一对应

  • 作业(Job)是程序的另一个状态,是指程序从被选中运行直到运行结束的整个过程。
    • 所有作业都是程序,但不是所有程序都是作业。
    • 当一个作业被选中后进入内存运行,这个作业就成为进程。
    • 进程都是作业,但不是所有的作业都是进程。正在运行的作业才是进程
    • 作业是介于程序和进程之间的一种状态
进程的描述
三种基本状态
  • 就绪状态:

    • 当进程已分配到除CPU以外的所有必要资源后, 只要再获得CPU,便可立即执行
  • 执行状态:

    • 进程已获得CPU,其程序正在执行
  • 阻塞状态:

    • 正在执行的进程由于发生某事件而暂时无法继续执行时,便放弃处理机而处于暂停状态,把这种暂停状态称为阻塞状态,有时也称为等待状态。
    • 主动放弃
  • 五种状态及其转换模型:
    *

  • 进程的挂起状态:

    • 活动到静止,由内存到外存
    • 这种静止状态称为挂起状态
  • 进程挂起的原因

    • 终端用户的请求
    • 父进程请求
    • 负荷调节的需要。当实时系统中的工作负荷较重, 把一些不重要的进程挂起,以保证系统能正常运行
    • 操作系统的需要。操作系统有时希望挂起某些进程, 以便检查运行中的资源使用情况或进行记账
  • 被挂起进程的特征

    • 不能立即执行
    • 可能是等待某事件发生,若是,则阻塞条件独立于挂起条件,即使阻塞事件发生,该进程也不能执行
    • 使之挂起的进程为:自身、其父进程、OS
    • 只有挂起它的进程才能使之由挂起状态转换为其他状态
  • 阻塞和挂起的区别:

    • 进程是否等待事件,阻塞与否
    • 进程是否被换出内存,挂起与否
  • 四种状态的组合
    *
    *

  • 中级调度
    *

进程控制块PCB
  • 常驻内存

  • 是进程存在的唯一标志

  • PCB作用

    • 作为独立运行的基本单位的标志
    • 实现间断性运行方式
    • 提供进程管理所需要的信息
    • 提供进程调度所需要的信息
    • 实现与其他进程同步与通信
  • pcb中的
    *
    *

3.进程控制

  • 即对系统中 所有的进程实施有效的管理,其功能包括

    • 进程的创建
    • 进程的撤销
    • 精诚达阻塞与唤醒
  • 进程控制一般是由OS的内核中的原语(Primitive)来实现的

  • 执行模式:

    • 核心态(管态):
      • 由设备中断、异常、自陷(即软中断 )等进入,这种状态具有较高的特权,允许使用全部机器资源与机器指令,是操作系统程序执行时的状态
    • 用户态(目态):
      • 处理机在这种状态下只能使用指定的机器指令,不能使用如I/O、改变机器状态、修改存储保护 等指令,并且只允许访问用户自己的存储区,是用户程序执行时的状态。
  • 支撑功能:

    • 进程管理:进程的调度与分派、进程的创建与撤消等;进程同步的原语、常用的进程通信原语
    • 存储器管理:地址转换机构、内存分配与回收的功能模块、以及实现内存保护和对换功能的模块等
    • 设备管理:由于设备管理与硬件(设备)紧密相关,因此其中很大部分也都设置在内核中
原语
  • 由若干条指令组成的,是用于完成一定功能的一个过程
  • 原语是原子操作:一个操作中的所有动作要么全做,要么全不做。(操作不可中断)
  • 原子操作在系统态下执行,常驻内存
进程的创建
  • 父进程

  • 子进程 – 可以继承父进程所拥有的资源

  • 当子进程被撤消时,应将其从父进程那里获得的资源归还给父进程。

  • 在撤消父进程时,也必须同时撤消其所有的子进程

  • 引起创建进程的事件
    *

  • 创建过程

    • 进程的创建fork()借用现实世界的“克隆”技术
      • 子进程克隆父进程,但不仅如此。而是采用了“写时复制 技术
      • 父进程并不是把自己的所有东西马上都给儿子, 是直到儿子真正需要时才给它。
      • fork()的实际开销就是复制父进程的页表以及给子进程创建唯一的PCB
进程的终止
  • 正常结束:

    • 批处理中用Holt指令,分时中用Logs off指令
  • 引起进程终止的事件:

进程的阻塞与唤醒
  • 引起阻塞的事件

    • 请求系统服务:提出I/O服务时,并不立即满足该进程的要求时,转变为阻塞状态来等待
    • 启动某种操作:当进程启动某种操作后,在该操作完成之后才能继续执行
    • 新数据尚未到达:对于相互合作的进程而言
    • 无新工作可做。如发送进程
  • 进程阻塞过程

    • 正在执行的进程,当发现上述某事件时,由于无 法继续执行,于是进程便通过调用**阻塞原语 block( )**把自己阻塞。
    • 进程控制块中的现行状态由“执行”改为“阻塞” ,并将PCB插入阻塞队列
    • 转调度程序进行重新调度,将处理机分配给另一就绪进程,并进行切换
  • 进程的唤醒:

    • 当被阻塞进程所期待的事件出现时,则由有关进程(比如,用完并释放了该I/O设备的进程) 调用唤醒原语wakeup( ),将等待该事件的进程唤醒
  • 唤醒过程

    • 首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其PCB中的现行状态由阻塞改为就绪
    • 然后再将该PCB插入到就绪队列中
  • Block原语和Wakeup原语

    • Block原语和Wakeup是一对作用相反的原语;
进程的挂起与激活
  • 当出现了引起进程挂起的事件时,系统将利用**挂起原语 suspend( )**将指定进程进程挂起。
  • 执行过程:
    • 首先检查被挂起进程的状态,若处于活动就绪状态,便将其改为静止就绪
    • 对于活动阻塞状态的进程,则将之改为静止阻塞状态

4.进程同步

  • 基本概念
    • 间接相互制约关系。由于资源共享
    • 直接相互制约关系。主要由于进程间的合作
  • 临界资源
    • 一次仅允许一个进程访问的资源
1.生产者消费者问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 代码外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 临界区:

    • 每个进程中访问临界资源的那段代码
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 进程同步的基本概念

    • 空闲让进
    • 忙则等待
    • 优先等待
    • 让权等待
  • 临界区互斥问题的解决:

    • 硬件同步机制
    • 信号量机制
    • 管程机制
2.硬件同步机制
  • 对临界区管理将标识看做一个锁,“锁开”进入, “锁关”等待。

  • 初始打开,每个进入临界区的进程必须对锁进行测试。

  • 测试和关锁操作必须连续(原子操作)

  • 过程:

    • 关中断
    • 利用Test-and-Set指令实现互斥
      • TS指令是用硬件实现的
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 利用Swap指令实现互斥
      • 也是由硬件实现且不允许被中断
      • 逻辑上和TS指令一样
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 优点:

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 缺点:

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
3.信号量(Semaphores)机制
  • 整型信号量
  • 记录型信号量
  • AND型信号量
  • 信号量集
整形信号量
  • 定义为一个整型量 ,**仅能通过两个标准的原子操作 wait(S)和signal(S)**来访问。又称为P、V操 作。
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • P、V操作(即wait(s)和signal(s))为原语操作—
  • 使用:
    • 必须置一次且只能置一次初值,并且初值不能为负数。
    • 只能执行P、V操作
    • 必须成对使用P、V操作:P操作遗漏则不能保证互斥访问,V操作遗漏则不能在使用临界资源之后将其释放;P, V次序不能错误、重复或遗漏。
    • 整型信号量的缺点:未遵循同步机制的“让权等待”, 一直判断是否处理完,占用处理机。
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
记录型信号量
  • 对value的值先–或者先++

  • 若value的值小于0,value的绝对值就是等待队列中进程个数

  • 处理过程:

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
      • 将该进程阻塞,放入等待队列
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
      • S.value≤0,说明该进程释放之后仍然有进程在等待队列,需要唤醒
  • 整型信号量与记录型信号量的问题讨论

    • 信号量的物理含义:

      • 信号量的初值S或者S.value应该大于等于0. S.Value的初值表示系统中某类资源的数目,称为资源信号量

      • 若S.value初值为1,只允许一个进程访问临界资源,信号量转化为互斥信号量,用于进程互斥

      • S.value>0表示有S.value个资源可用

      • S.value=0表示无资源可用

      • 记录型信号量: 若S.value<0,则| S.value|表示S等待队 列中的进程个数

      • P(S):表示申请一个资源

      • V(S):表示释放一个资源

    • 优点:

      • 简单,而且表达能力强(用P.V操作可解决任何同步 互斥问题
    • 缺点:

      • 不够安全;P.V操作使用不当会出现死锁;只能用于共享一个临界资源, 遇到如多个临界资源等情况下的复杂同步互斥问题时实现复杂外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
AND信号量
  • 将进程在整个运行过程中需要的所有资源,一次性全都地分配给进程,待进程使用完后再一起释放。只要尚有一个资源未能分配给进程, 其它所有可能为之分配的资源,也不分配给他
  • wait操作中,增加了一个“AND”条件,故称为 AND同步,或称为同时wait操作。
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 信号量集
    • 一般信号量集是指同时需要多种资源每种占用的数目不同且可分配的资源还存在一个临界值时的信号量处理
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
利用信号量机制实现进程同步

semaphore S =0 初始化同步信号量为0

image-20230613090622851

加入代码4的执行必须在代码2之后,那么如上图所示

在先执行的代码后执行V操作,后执行的代码前执行P操作

  • 前V后Pimage-20230613091345621
利用信号量实现进程互斥
  • 为使多个进程能互斥地访问某临界资源,只须为该资源设置一互斥信号量mutex,并设其初始值为1,然后将各进程访问该资源的临界区 CS置于wait(mutex)和signal(mutex) 操作之间即可
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 注意:
    • wait(mutex)和signal(mutex)必须成对出现
    • 缺少wait(mutex)导致系统混乱,不能保证对临 界资源的互斥访问;
    • 缺少signal(mutex)会使临界资源永远不释放,等待该资源的进程不能被唤醒
生产者消费者问题
  • full:表示当前队列中已有的个数
  • empty:表示当前队列中还可以放的数据个数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

利用记录性信号量解决问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 当为互斥操作时,PV处于同一进程
  • 当为同步操作时,pv不在同一进程
  • 如果P(S1)和P(S2)两个操作在一个进程中,那么P操作的顺序至关重要,一个同步P操作与一个互斥P操作在一起时,同步P操作在互斥P操作之前
  • 两个V操作的顺序无关紧要
利用AND信号量解决问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

多生产者多消费者

image-20230613093339101

  • 当缓冲区容量为1时,不要互斥信号量也不会发生死锁,但是若缓冲区数量大于1时,会发生死锁
哲学家进餐问题
利用记录型信号量解决问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 情况一:
    • 设置互斥信号量的容量为4 semaphore count=4
利用AND信号量解决问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 即一个哲学家同时拿起左右两根筷子
读写者问题
  • 如何解决读进程优先问题

    • 再加一个互斥信号量semaphore w=1image-20230613101102174
    • 满足FCFS原则
  • 计数器count

    • 实现了读者质之间不互斥,
  • rw信号量

    • 实现了读者写者之间互斥的问题
  • mutex信号量

    • 保证了操作的一气呵成,避免出现错误
  • 对于系统中的共享对象,把只要求读该文件的进程称为“reader进程”,其它进程称为“writer进程

  • 所谓读者-写者问题,是指保证一个write进程必须与其它进程互斥地访问共享对象的同步问题

利用记录性信号量解决问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

信号量集解决读者—写者问题

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.进程通信

管道
  • 管道:连接一个读进程和一个写进程之间通信的共享文件

  • 进程之间的信息交换

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 进程通信的类型:
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
直接通信方式
  • 指发送和进程利用OS所提供的发送命令,直接把消息发送给目标进程
  • 系统提供下述两条通信命令(原语):
    • Send (Receiver, message)
    • Receive(Sender, message)
  • 消息传递通信的实现方法:
    • image-20230613111141662
间接通信
  • 进程之间利用信箱的通信方式。发送进程发送给目标进程的信息存放信箱;
  • 接收进程则从该信箱中取出对方发送给自己的消息
  • 消息在信箱中可以安全地保存, 只允许核准的目标用户随时读取。
  • 优点:
    • 在读/写时间上的随机性
    • 写进程->信箱(中间实体)->读进程原语
    • 消息的发送和接收
      • Send (mailbox, message)
      • Receive (mailbox, message)

第三章 处理机调度与死锁

调度机调度层次与目标

  • 低级调度:
    • 进程调度,短程调度
  • 中级调度:
    • 交换调度, 中程调度
  • 高级调度:
    • 作业调度,长程调度

高级调度:
  • 调度对象:作业

    • 又称作业调度长程调度、接纳调度
    • 实现:
      • 作业管理程序
    • 外存作业调入内存创建PCB等,插入就绪队列。
    • 用于批处理系统,分/实时系统一般直接入内存,无此环节。
    • 频度:最低,分钟级
  • 长程调度模型:

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
低级调度
  • 又称进程调度短程调度
  • 对象:就绪进程(或内核线程
  • 功能:决定就绪队列中的那个进程应获得处理机,并将处理机分配给选中的进程
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 应用范围:都有
  • 频度:最频繁,毫秒级
  • 引起低级调度的因素
    • 正在执行的进程执行完毕,或因发生某件事情而不能再继续执行
    • 执行中的进程因提出I/O请求而暂停执行
    • 在进程通信或同步过程中执行了某种原语操作, 如P操作(wait操作)、Block原语、 Wakeup原语等
中级调度
  • 又称内存调度、中程调度

  • 对象:挂起的进程

  • 功能:把外存上那些已经具备运行条件的就绪进程重新载入内存。从静止就绪到活动就绪

  • 应用范围**:具有对换功能的操作系统**

  • 频度**:中等**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

处理机调度算法的目标
  • CPU利用率 = CPU的有效工作时间 / (CPU 有效工作时间 + CPU空闲等待时间)
  • 公平性
  • 平衡性
  • 策略强制执行
批处理系统的目标
  • 吞吐量:

    • 单位时间内系统所完成的作业数
    • 系统吞吐量高:尽量多地选择短作业运行
    • 处理机利用率高:尽量选择计算量大的作业
    • 两者目标存在一定矛盾
  • 平均周转时间

    • 周转时间:包括四部分
      • 作业在外存后备队列上等待调度的时间
      • 进程在就绪队列上等待进程调度的时间
      • 进程在CPU上执行的时间
      • 进程等待I/O操作完成的时间
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 带权周转时间作业的周转时间T与系统为它提供服务的时间Ts之比。 W = T/Ts
    • 带权周转时间标明了作业额外等待和作业执行时间之间的比例
    • 平均带权周转时间反应调度算法的好坏
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 吞吐量

    • 指在单位时间内系统所完成的作业数,因而它与批处理作业的平均长度具有密切关系。
    • 系统吞吐量高:尽量多地选择短作业运行
    • 处理机利用率高:尽量选择计算量大的作业
分时系统的目标
  • 响应时间:
    • 从用户通过键盘提交一个请求开始,直到屏幕上显示出处理结果为止的一段时间间隔
    • 包括三个部分:
      • 输入时间
      • 处理时间
      • 显示时间
  • 响应时间快:分时系统的重要准则
  • 均衡性:指系统响应时间的长短应与用户所请求服务的复杂性相适应
实时系统的目标
  • 截止时间的保证:
    • 开始截止时间
    • 完成截止时间
    • 硬实时、软实时
  • 可预测性:
    • 对调度结果的可预见性

作业和作业调度

批处理系统中的作业
  • 作业 Job:用户提交给系统的一项相对独立的工作。程序+数据+作业说明书

  • 作业步:

    • 在作业运行期间,每个作业都必须经过若干个相对独立,又相互关联的顺序加工步骤才能得到结果,每一个加工步骤称为一个作业步,各作业步之间存在着相互联系。

    • 作业流:依次执行的作业步,作业步间非并行的

  • 作业控制块 JCB

    • 作业管理系统用于管理和控制作业运行的数据结构
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 作业运行的三个阶段和三种状态

    • 收容阶段:后备状态
    • 运行阶段:运行状态
    • 完成阶段:完成状态
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
作业调度的主要任务
  • 根据JCB信息,检查系统中的资源能否满足作业对资源的需求,按照一定的调度算法,从外存的后备队列中选取某些作业调入内存,并为他们创建进程、分配必要资源, 安排在就绪队列。

  • 作业调度需要作出以下决定:

    • 接纳多少个作业 (多道程序度)
    • 接纳哪些作业

作业调度

  • 周转时间:完成时间-到达时间
  • 带权周转时间:周转时间/运行时间
  • 等待时间=周转时间-运行时间
  • 以上三种的平均:求和之后再除以数量image-20230613131534359
先来先服务调度算法(FCFS)
  • 按照作业提交或进程变为就绪状态的先后次序,分派CPU;当前作业或进程占用CPU,直到执行完或阻塞,才主动地出让CPU。
  • FCFS算法比较有利于长作业(进程),而不利 **短作业(进程)**FCFS调度算法有利于CPU繁忙型的作业,而不利于I/O繁忙型的作业
  • FCFS调度算法有利于CPU繁忙型的作业,而不利于I/O繁忙型的作业
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
短进程/作业优先调度算法(SJF)
  • 短作业(进程)优先调度算法SJ§F:
    • 是指对短作业或短进程优先调度的算法。它们可以分别用于作业调度和进程调度
    • 是从后备队列中选择一个或若干个估计运行时间最短的作业,将它们调入内存运行
    • 是从就绪队列中 选出一估计运行时间最短的进程将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时,再重新调度
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 抢占式的SJF
    • image-20230613132005424
    • image-20230613132013512
    • 执行是断断续续的
  • 优点:
    • 能有效降低作业的平均等待时间
    • 提高吞吐量
    • 能有效缩短进程的周转时间
  • 缺点:
    • 对长作业不利
    • 不考虑作业的紧迫程度
    • 作业执行时间、剩余时间仅为估计时间; 故SJ§F算法虽然是优化的,但在CPU调度中很难实现
    • 会导致饥饿
优先级调度算法(PSA)
  • 外部赋予作业(进程)相应的优先级,例如以作业的紧迫程度作为优先级
  • 选择优先级高的进程投入运行
  • 既可用于作业调度算法,也可用于进程调度
高响应比优先调度算法(HRRN)
  • 既照顾短作业又不使长作业的等待时间过长,改进了调度性能

  • 优先权=(等待时间+要求服务时间)/要求服务时间=响应时间/要求服务时间=Rp外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • image-20230613132540453

  • 避免了长作业饥饿的情况。不会导致饥饿

进程调度

  • 进程调度的任务:
    • 保存处理机现场
    • 按照某种算法选取进程
    • 把处理机分配给进程
  • 进程调度方式
    • 非抢占式:
      • 一旦进程投入运行,除了进程完成或者需要阻塞外,不能剥夺其处理机
      • 采用这种方式时,引起调度的原因可归结为:
        • 进程运行完毕或因发生某事件而无法继续运行
        • 因I/O请求而阻塞
        • 因通信或者同步而阻塞
    • 抢占式:
      • 允许根据某种原则,暂停正在执行的进程,重新分配处理机
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
轮转调度算法RR
  • 分时系统的需求:

    • 每个进程仅运行一个时间片即被抢占CPU
  • 原理:

    • FCFS策略+时钟中断+时间片原则
  • 进程切换时机:

    • 时间片内进程结束,进程结束事件激活进程调度新进程可运行一个时间片
    • 时间片用完,时钟中断激活调度,旧进程到就绪队列尾,队头进程投入运行一个时间片
  • 时间片大小的确定:

    • 太小:利于短作业,但增大调度和上下文切换频率,增大系统开销
    • 太长:退化为FCFS算法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

优先级调度算法
  • 类型:

    • 非抢占式优先级调度算法image-20230614091437380
    • 抢占式优先级调度算法
      • 就绪队列发生改变时需要检查是否会发生抢占image-20230614091904910
  • 优先级的类型:

    • 静态优先级
      • 静态优先级是在创建进程时确定的,且在进程的整个运行期间保持不变。
    • 动态优先级
      • 在创建进程时所赋予的优先权, 是可以随进程的推进或随其等待时间的增加而改变的,以便获得更好的调度性能
  • 优点

    • 用优先级区分紧急程度、重要程度,适用于实时操作系统。
  • 缺点

    • 若源源不断的高优先级进程到来,则可能导致饥饿
多队列调度算法
  • 基本思想:
    • 多级反馈队列调度算法是时间片轮转算法和优先级调度算法的综合和发展,通过动态调整进程优先级和时间片大小,不必事先估计进程的执行时间,多级反馈队列可兼顾多方面的系统目标,是目前公认的一种较好的进程调度算法
    • 抢占式的
  • 实施过程:
    • 设置多个就绪队列,并为各个队列赋予不同的优先级。 第一个最高,以后依次降低
    • 每个队列中进程执行时间片的大小也各不相同,进程所在队列的优先级越高,其相应的时间片就越短
  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 当一个新进程进入内存后,首先将它放入第一队列的末尾,按FCFS原则排队等待调度。当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,再同样地按FCFS原则等待调度 执行;如果它在第二队列中运行一个时间片后仍未完成, 再依次将它放入第三队列
    • 仅当第一队列空闲时,调度程序才调度第二 队列中的进程运行
  • 未执行完时间片的进程被抢占后如何处理?
    • 不降级,到队列末尾,且下一次运行时仍然是一个完整时间片(该队列对应的)
基于公平原则的调度算法
  • 保证调度算法:
    • 保证的是绝对运行时间,即启动后在某个时间段内必须获得多少运行时间
      • 例如N个进程平均分配时间
  • 公平分享调度算法:
    • 按照用户数量平均分配时间,而不是进程间平均分配

实时调度

  • 由于在实时系统中都存在着若干个实时进程或任务
  • 实时任务分类:
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

死锁概念

  • 死锁:

    • 是指多个进程在运行过程中因争夺资源而造成的一种僵局
    • 当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。
  • 死锁进程都不能:

    • 运行
    • 释放资源
    • 被唤醒
  • 一些结论:

    • 参与死锁的进程最少是两个,两个以上进程 (线程)才会出现死锁
    • 参与死锁的进程至少有两个已经占有资源
    • 参与死锁的所有进程都在等待资源
    • 参与死锁的进程是当前系统中所有进程的子集
  • 产生死锁的原因可归结为两点:

    • 竞争资源
      • 可重用资源的竞争
      • 可消耗资源的竞争
    • 进程间推进顺序非法
  • 竞争临时资源:

    • 临时性资源,可以创造(生产)和撤消(消耗) 的资源,也称之为消耗性资源,它也可能引起死锁。如信号量、消息、buffer中的
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 进程推进顺序不当引起死锁:

    • 若并发进程P1和P2推进顺序不合法,进 入不安全状态,于是发生了进程死锁
  • 当资源不够时,不一定死锁

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 当进程推进到死锁区时,进程必死
    • 可通过增加资源来解决死锁,比如有两个r1和 两个r2资源就不会发生死锁,但现实中是不可取的

死锁的定义、必要条件和处理方法

  • 如果一组进程中的每一个进程都在等待仅由该组 进程中的其他进程才能引发的事件,那么该组进程是死锁的

  • 进程互斥的四个必要条件

    • 互斥条件
    • 请求和保持条件
    • 不剥夺条件
    • 环路等待条件
  • 死锁的解决方法

    • 预防死锁:
      • 是通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来预防发生死锁。
    • 避免死锁:
      • 是在资源的动态分配过程中, 用某种方法去防止系统进入不安全状态,从 而避免发生死锁
    • 检测死锁:
      • 通过系统所设置的检测机构, 及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源
    • 解除死锁:
      • 当检测到系统中已发生死锁时, 须将进程从死锁状态中解脱出来。常用的实施方法是撤消或挂起一些进程

预防死锁

  • 必须设法破坏产生死锁的 四个必要条件之一

    • 互斥条件:禁止互斥条件
      • 不能被改变
    • 请求和保持条件:禁止占有且等待条件
    • 不剥夺条件:禁止不剥夺条件
    • 环路等待条件:禁止环路等待条件
  • 其中必要条件1,因为它是由设备的固有属性所决定的, 不仅不能改变,还应加以保证

  • 破坏请求和保持条件

    • 系统规定所有进程在开始运行之前,都必须一次性地申请其在整个运行过程所需的全部资源
    • 从而进程在整个运行期间,便不会再提出资源要求,从而摒弃了请求和保持条件,由此可以避免发生死锁。
    • 优点:
      • 简单、易于实现且很安全
    • 缺点:
      • 资源被严重浪费,使进程被延迟运行
      • 可能会导致进程饥饿
  • 摒弃不剥夺条件

    • 一个已经保持了某些资源的进程再提出新的资源请求而不能立即得到满足时必须释放它已经保持了的所有资源。待以后需要时再重新申请。从而 摒弃了“不剥夺”条件。
    • 缺点:实现复杂并且付出代价很大
      • 一个资源在使用一段时间后,它的被迫释放可能会造成前段工作的失效
      • 会使进程前后两次运行的信息不连续
      • 反复地申请和释放资源,致使进程执行被无限推迟,延长进 程周转时间、增加系统开销、降低吞吐量
      • 之前获得的资源全部放弃,可能会导致进程饥饿
  • 摒弃环路等待条件

    • 系统将所有资源按类型进行线性排队,并赋予不同的序号所有进程对资源的请求必须严格按照资源序号递增的次序提出
      • 一个进程只有已占有小编号的资源时,才有资格申请更大的编号。
      • 占有更大编号的资源的进程不能逆向的申请小编号的资源
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 优点:资源利用率和系统吞吐量都有明显的改善
    • 存在的问题:
      • 首先是为系统中各类资源所分配(确定)的序号,必须相对稳定,这就限制了新类型设备的增加
      • 作业(进程)使用各类资源的顺序,与系统规定的顺序不同**,造成对资源的浪费**
      • 限制用户简单、自主地编程,编程麻烦

    image-20230614094605140

  • 系统的安全状态:

    • 安全状态:
      • 所谓安全状态,是指系统能按某种进程顺序, 若依次为n个进程分配其所需资源,直至其最大需求,使每个进程都可顺 利地完成,称系统处于安全状态
    • 称〈P1,P2,…,Pn〉序列为安全序列。否则, 如果系统无法找到这样一个安全序列,则称系统处于不安全状态
  • 安全、不安全、死锁状态空间

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 一个系统在安全状态,就没有死锁
    • 一个系统处于不安全状态,就有可能死锁
    • 避免死锁的实质:确保系统不进入不安全状态

银行家算法(死锁避免)

  • 避免死锁的关键在于如何准确的预测是否会出现死锁,从而避免死锁

  • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 银行家算法中的数据结构

    • n个进程(P1,P2,…,Pn)
    • m类资源(R1,R2,…,Rm)
    • 可利用资源向量:available[j]=k, 资源Rj类有k个可用
    • 最大需求矩阵:Max[i,j]=k,进程Pi最大请求k个Rj类资源
    • 分配矩阵:Allocation[i,j]=k,进程Pi分配到k个Rj类资源
    • 需求矩阵:Need[i,j]=k,进程Pi还需要k个Rj类资源
    • 三个矩阵的关系:
      • Need [i, j] = Max[i, j] – Allocation [i, j]
  • 算法步骤:

    • 1.如果Requesti [j]≤Need[i,j],便转向步骤2;否则认为出错,因为它所需要的资源数已超过它 所声明的最大值

    • 2.如果Requesti [j]≤Available[j],便转向步(3), 否则,表示尚无足够资源,Pi须阻塞等待

    • 3.系统试探着把资源分配给进程Pi,并修改下面数 据结构中的数值:

      • Available[ j ] = Available[ j ] - Requesti [ j ]
      • Allocation[ i,j ] = Allocation[ i,j ] + Requesti [ j ]
      • Need[ i, j ] = Need[ i, j ] - Requesti [ j ]
        • 注意这是假分配
    • 4.系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态

  • 若安全,才正式将资源分配给进程Pi,以完成本次分配

    • 否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待
  • 安全性算法

    • 1.设置两个向量:

    • 工作向量Work: 它表示系统可提供给进程继续运行所需的各类资源数目,Work = Available

      • Finish:开始时先做Finish[i] = false;当有足够资源分配给进程时,再令Finish[i] = true

      • 2.从进程集合中找到一个能满足下述条件的进程:

      • Finish[i] = false

      • Need[i,j] ≤ work[j];

        • 若找到,执行步骤(3);否则,执行步骤(4)
    • 3.当进程只获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:

  • Work[ j ] = Work[ i ] + Allocation[ i,j ]
    * Finish[ i ] = true
    * go to step 2

  • 4.如果所有进程的Finish[i] = true都满足,则 表示系统处于安全状态;否则,系统处于不安全状态image-20230614101908265

  • 避免死锁的限制:

  • 避免死锁不像预防死锁那样需要剥夺进程已获得的资源,或重新执行进程。而且,避免死锁比预防死锁施加的

    • 限制条件
      • 预先必须申明每个进程需要的资源总量
      • 进程之间相互独立,其执行顺序取决于系统安全,而非进程间的同步要求
      • 系统必须提供固定数量的资源供进程使用
  • 银行家算法的应用:

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
  • 补充:

    • n个进程m个资源,若每个进程都需要用该类资源,而且**各进程对类资源的最大需求量之后小于m+n,说明系统不会因竞争该类资源而死锁 **
    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

死锁的检测与解除

  • 当系统为进程分配资源时,若未采取任何限制性措施,则系统必须提供检测和解除死锁的手段

  • 检测死锁的基本思想:

    • 利用某种算法资源请求和分配信息加以检查,以判断是否存在死锁
  • 资源分配图G = (N,E):

    • 把N分为两个互斥的子集,即一组进程结点P={P1,P2,…,Pn) 和一组资源结点R={r1, r2, …, rn}, N=P U R
    • 凡属于E中的一个边e∈ E都连接着P中的一个结点和R中的一个结点
    • e={Pi,rj} 它表示进程pj请求一个单位的rj资源
    • e={rj,Pi} 它表示把一个单位的资源rj分配给进程Pi
  • 死锁定理:

    • 有环路且有死锁的资源分配图
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 有环但没有死锁的资源分配图
      • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 重要结论:
      • 如果资源分配图中不存在环路,则系统中不存在死锁;反之,如果资源分配图中存在环路,则系统中可能存在死锁,也可能不存在死锁
  • 死锁检测算法

    • (1)寻找一个既不阻塞又非孤立的进程结点Pi,若无,则算法结束
    • (2)去除Pi的所有分配边和请求边,使Pi成为一个孤立节 点
    • (3)转步骤(1)
    • 若能消去资源分配图中所有结点的连接边,使全部结点都成为孤立结点,则称该图是可完全简化图若不能使该图完全简化,则称该图是不可完全化简图
    • 当且仅当系统某状态S所对应的资源分配图是不可完全化简的,则S是死锁状态。该充分条件称为死锁定理
死锁的解除
  • 常采用的两种方法:

    • 剥夺资源。从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态
    • 撤消进程。最简单的撤消进程的方法, 是使全部死锁进程都夭折掉;或者按照某种 顺序逐个地撤消进程,直至有足够的资源可用,使死锁状态消除为止
  • 进程回退。让一个或多个死锁进程回退到足以避免死锁的地步

  • 按照解除死锁复杂度递增的顺序列出解除死锁的方法:

    • 撤消死锁进程。该方法是目前操作系统中解除死锁的常用方法
    • 死锁进程恢复到前一个检查点,重新执行每个进程
    • 按照某种原则逐个选择死锁进程进行撤消,直到解除系统死锁
    • 按照某种原则逐个剥夺进程资源,直到解除死锁
  • 最小代价原则

    • 第三种和第四种方法需要选择系统付出代价最小的进程,最小代价原则
    • 到目前为止,花费处理机的时间最少的进程
    • 到目前为止,产生输出最少的进程
    • 估计未执行部分最多的进程
    • 到目前为止,已获得资源量最少的进程
    • 优先级最低的进程

第四章 存储器管理

可重定位装入方式

  • 经编译得到的目标模块中为相对地址(通常从0开始), 即地址都是相对于0开始的
  • 装入模块中的逻辑地址与实际装入内存的物理地址不同
  • 什么重定位
    • 装入内存时,相对地址(数据、指令地址)要作出相应的修改以得到正确的物理地址,这个修改过程称为重定位
为什么引入重定位

(地址映射/地址变换)

  • 装入模块中的逻辑地址与实际装入内存的物理地址不同,得到正确的物理地址
  • 更有效地使用内存资源

连续分配和离散分配

连续分配
  • 为用户程序分配一个连续的内存空间
    • 程序空间本来就是连续的
    • 用连续的内存装入连续的程序,减少管理工作的难度

image-20230615111704603

  • 连续分配的特点:
    • 简单高效:
      • 连续分配的管理方式相对简单,容易实现和操作,因为内存空间被划分为一系列连续的块
    • 低碎片化:
      • 由于进程所需的内存空间必须是连续的,因此可能会导致外部碎片的问题
    • 内存利用率较低:
      • 由于外部碎片的存在,连续分配可能导致内存利用率较低
  • 离散分配的特点:
    • 灵活性:
      • 离散分配允许进程的页面在物理内存中非连续地分配,因此能够更好地利用可用的内存空间,减少外部碎片的问题
    • 高内存利用率:
      • 由于离散分配可以更灵活地利用内存空间,因此可以提供较高的内存利用率。即使存在一些内部碎片,整体上仍然可以更好地满足进程的需求
    • 需要页表管理
      • 离散分配需要维护一个页表来跟踪进程的页面在物理内存中的位置,以及虚拟地址与物理地址之间的映射关系。这增加了一定的管理和维护开销

存储器的层次结构

  • 寄存器
  • 主存
  • 辅存image-20230601202317291
存储分配的三种方式
  • 直接指定方式

    • 程序员在编程序时,或编译程序 (汇编程序)对源程序进行编译(汇编)时,使用实际存储地址
    • 在多道程序环境下,应保证各作业所用的地址互不重叠
    • 前提
      • 存储器的可用容量(空间) 已经给定或者可以指定,这对单用户计算机系统是不成问题的。
    • 实质:
      • 由编程人员在编写程序时,或由编 译程序编译源程序时,对一个作业的所有信息确定在主存存储空间中的位置。因此,这种直接指定方式的存储分配方案, 不仅用户感到不便,而且存储空间的利用也不那么有效
  • 静态分配方式(Static Allocation)

    • 可从其 地址空间的零地址开始;当装配程序对其进行连接装入时才 确定它们在主存中的相应位置,从而生成可执行程序。也就 是说,存储分配是在装入时实现的

    • 特点:

      (1)在一个作业装入时必须分配其要求的全部存储量; (2)如果没有足够的存储空间,就不能装入该作业

      (3)一旦一个作业进入内存后,在其退出系统之前,它一 直占用着分配给它的全部存储空间

      (4) 作业在整个运行过程中不能在内存中“搬家”、也不 能再申请存储量

    • 静态分配策略的存储管理很简单,但在多道程序系统中 不能有效地共享存储器资源

  • 动态分配方式(Dynamic Allocation)

    • 动态分配是一种更加有效的使用主存储器的方法

    • 特点

      (1)作业在存储空间中的位置,也是在其装入时确定的

      (2)在其执行过程中可根据需要申请附加的存储空间; (3)一个作业已占用的部分存储区域不再需要时,可以要求归还给系统。 即:这种存储分配机制能接受不可预测的分配和释放存储区域 的请求,实现个别存储区域的分配和回收;

      (4)存储区域的大小是可变的;

      (5)允许作业在内存中“搬家”

程序的装入和链接

  • 将一个用户源程序变为一个可在内存中执行的程序,通常要经过下列几步
    • 编译
      • 源程序模块是用高级语言或汇编语言 写的一组程序语句。计算机不能直接执行源语句。编译程序(Compiler)接受完整的源一级的程序, 并以类似于成批的方式生成完整的目标一级的模块
      • 生成目标模块
    • 链接(Linker)
      • 目标模块是纯二进制的机器级 代码。计算机可以执行目标级代码,但是典型的目标模块是不完备的,它包含对其它目标模块(诸如存取方法或子例程)或库函数的引用。因此,目标模块通 常是不能装入计算机并执行的
      • 大部份目标模块必须首先链接成一个装入模块,这个使目标模块链接成装入模块的过程,是由链接程序(Linker)实现的
      • 生成装入木块
    • 装入(Loader):
      • 由装入程序将装入模块装入内存并执行
程序的装入
  • 绝对装入方式(Absolute Loading Mode)

    • 在编译时, 如果知道程序将驻留在内存的具体位置,那么编译程序将产生实际存储地址(绝对地址)的目标代码image-20230601205553892
  • 可重定位装入方式(Relocation Loading Mode)

    • 重定位(地址映射/地址变换):

      ➢ 经编译得到的目标模块中为相对地址(通常从0开始), 即地址都是相对于0开始的。

      ➢ 装入模块中的逻辑地址与实际装入内存的物理地址不 同。

      ➢装入内存时,相对地址(数据、指令地址)要作出相应 的修改以得到正确的物理地址,这个修改的过程称为重 定位。

    • 静态重定位

      • 装入内存时一次完成,且以后不能移动
      • 物理地址=相对地址+内存中的起始地址
  • 动态运行时装入方式(Denamle Run-time Loading) :

    • 装入程序将装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序执行时进行

连续分配存储管理方式

  • 指为用户程序分配一个连续的内存空间

  • image-20230601210250666

    image-20230601210628479

固定分区分配
  • 将内存用户空间划分为若干个固定大 小的区域,每个区域称为一个分区(region),在每个分区 中只装入一道作业 ,从而支持多道程序并发设计

  • 这些存储区域是在系统启动时划定的,其区域的大小和边界是不能改变的

  • image-20230601210746568

    • 分区说明表image-20230601210828228
  • 内碎片image-20230601211045894

  • 优点

    • 易于实现,开销小
  • 缺点

    • 内碎片造成浪费
    • 区总数固定,限制了并发执行的程序数目
    • 存储空间的利用率太低。现在的操作系统几乎不用它了
  • 采用的数据结构:分区表-记录分区的大小和使用情况

动态分区分配
  • 根据进程的实际需要,动态地为之分配连续的内存空间。即分区的边界可以移动,分区的大小是可变的。

  • 两种不同选择,一种是分区的数目固定大小是可变的,而另一种则允许分区的数目和大小都是可变的。为了说明它们之间的重要差异,我 们考虑一个具有256K字节存储器的系统

    image-20230601211438694

    image-20230601211451065

  • 可变分区分配

    • 数据结构image-20230601211617374
分区分配算法

image-20230601211651796

最佳适应算法(Best Fit:BF)
  • 就是为一作业选择分区时总是寻找其大小最接近作业所要求的存储区域。即:把作业放入这样的分区后剩下的零头最小

    • 按照容量递增排序
    • 每次分配完之后会重新进行排序
  • image-20230601211810194

  • image-20230601211820405

  • 缺点:

    • image-20230601211843256

    • 产生很多小的空白区

最坏适应算法(Worst fit: WF)
  • 按照容量递减排序
    • 每次分配后重新排序

image-20230601212716936

首次适应算法(First Fit: FF)
  • 每个空白区按其在存储空间中地址递增的顺序链在一起,即每个后继空白区的起始地址总是比前者的大。在为作业分配存储区域时,从这个空白区链的始端开始查找,选择第一个足以满足请求的空白块,而不管它究竟有多大

    • 每次都从低地址开始查找
  • image-20230601213059345

  • 优点:

    算法简单,查找速度快;留在高址 部分的大的空白区被划分的机会较少,因而在大作业 到来时也比较容易得到满足

  • 缺点:

    这种算法常常利用一个大的空白区适应小作业的请求,从而留下一些较小的无法用的空白区,存储空间利用率不高

    每次都从开始查找,将使找到合适空白区的速度降低

    image-20230601213715342

image-20230601213926745

下次适应算法(Next fit: NF)
  • 我们把存储空间中空白区构成一个循环链。每次为存储请求查找合适的分区时,总是从上次查找结束的地方开始,只要找到一个足够大的空白区,就将它划分后分配出去
    • 按照地址递增,但是不会重头开始检索
    • 循环链表
  • 可能导致大进程无法使用
快速适应算法(Quik fit: QF)
  • 将空闲分区根据其容量大小进行分类,对于每一类具有相同容量的所有空闲分区,单独设立一个空闲分区链表,这样,系统中存在多个空闲分区链表
  • 在内存中设立一张管理分区类型,并记录了该类型空闲分区链表表头的索引表,该表的每一个表项记录了对应类型空闲分区链表表头的指针
  • image-20230601214553175
例题
  • image-20230615105943139
  • image-20230615110202325
    *
分区分配
  • 主要操作有分配内存回收内存。这些操作是在程序接口中通过系统调用发出的
  • 分配内存:
    • 它并不要求这个分配的存储区域限于特定的位置,但 是,这个区域必须是连续的

基本分页存储管理方式

空间划分
  • 页:

    • 将一个用户进程的地址空间(逻辑)划分成若干个大小相等的区域,称为页或页面Page
  • 块:

    • 内存空间也分成若干个与页大小相等的区域,称为(存储、物理)块或页框(Frame),同样从0开始编号、
  • 如何建立程序空间与主存空间的映射image-20230605201258786

基本分页存储管理
  • 把每个作业全部装入内存后方能运行
  • 不具有支持实现虚拟存储器的功能。
  • 主要特征
    • 一次性
      • 要求将作业全部装入内存后方能运行
    • 驻留性
      • 作业装入内存后,便一直驻留在内存中, 直至作业运行结束
页表
  • 页面大小的选择
    • 由机器的地址结构决定某一机器只能采用一种大小的页面
  • 实现分页存储管理的数据结构
    • 页表
      • 每个进程对应 1 个页表,描述该进程的各页面在内存中对应的物理块号
      • 页表中包括页号、物理块号
      • 全部页表集中存放在主存的系统专用区中,只有系统有权访问页表,保证安全
    • 作业表
      • 整个系统1张,记录作业的页表情况,包含进程号、页表长度、页表始址等信息
    • 空闲块表:
      • 整个系统1张,记录主存当前空闲块

image-20230605202251036

  • 页表的作用:

    • 实现从页号到物理块号的地址映射
  • 页表一般存放在内存

  • 页表的基址及长度由页表寄存器给出

  • 访问一个数据/指令需访问内存2次(页表一次,内存一次),所以出现内存访问速 度降低的问题。image-20230605202719579

  • 例题image-20230605202926015

    image-20230605202934781

  • 地址结构image-20230605203240607

  • egimage-20230605203316244

  • image-20230605203640421

基本的地址变换机构
  • 页表寄存器(PTR),记录当前运行的进程的页表在内存中的始址和页表长度。(平时存于PCB中, 要运行时才装入PTR中)

(1)根据逻辑地址,计算出页号和页内偏移量;

(2)从PTR中得到页表首址,然后检索页表,查找指定页面对应的页框号

(3)用页框号乘以页面大小获得其对应的起始地址, 并将其送入物理地址的高端。

(4)将页内偏移量送入物理地址低端,形成完整的物理地址image-20230605204325984

  • 例题image-20230605204513750

    image-20230605204615756

  • 例题image-20230605204629368

    image-20230605205222454

  • 例题image-20230605205240603

具有快表(TLB)的地址变换机构
  • 分页系统中处理机每次存取指令或数据至少需要访问两次物理内存:

➢第一次访问页表,以得到物理地址

➢第二次访问物理地址,以得到数据

  • 快表的工作原理类似于系统中的数据高速缓存 (cache),其中专门保存当前进程最近访问过的一组页表项
  • ➢若快表中存在该表项,称为命中(hit),取出其中的页框号,加上页内偏移量,计算出物理地址。
  • ➢若快表中不存在该页表项,称为命中失败,则再查找页表,找到逻辑地址中指定页号对应的页框号。同时,更新快表,将该表项插入快表中。并计算物理地址
访问内存的有效时间 EAT

image-20230605210120368

两级页表和多级页表

① 采用离散分配方式来解决难以找到一块连续的大内存空间的问题,(即引入两级页表);

② 只将当前需要的部分页表项调入内存, 其余的页表项仍驻留在磁盘上,需要时再调入

image-20230605220532424

基本分段存储管理方式
为什么引入分段存储管理
  • 便于编程
    • 按逻辑关系划分成为若干个段
  • 分段共享
    • 实现程序和数据的共享。段是信息的逻辑单位,有利于信息的共享
  • 分段保护
    • 信息保护是对相对完整意义的逻辑单位进行保护
  • 动态链接
  • 动态增长
分段共享
  • 一般实现程序和数据共享时都是以信息的逻辑单位 (过程、函数或文件)为基础的
  • 在分页系统中的每一页都只是存放信息的物理单位,其本身并无完整意义,因而不便于实现信息共享
  • 段是信息的逻辑单位,可以为共享过程建立一个独立的段,更便于实现程序和数据的共享
分段保护
  • 对内存中的信息的保护,同样也是对信息的逻辑单位进行保护
  • 采用分段存储管理,对实现保护,将是更有效和方便。
动态链接
  • 程序运行时,先将主程序所对应的目标程序装入内存并启动运行,当运行过程中又需要调用某段 时,才将该段调入内存并进行链接
动态增长
  • 在实际使用中,往往有些段,特别是数据段会随 着程序的运行不断增大,而这种增长事先并不知 晓会增长到多大,采用其它存储管理方式是难以 应付的,而分段存储管理却能较好的解决这一问题
分段和分页的主要区别

image-20230606111811186

段页式存储管理方式
  • 分页管理内存管理效率高

    • 没有外零头
    • 零头小
  • 分段管理符合模块化思想

    • 每个分段都具备完整的功能
    • 方便代码共享、保护
    • 没有内零头,存在外零头
  • 原理:

  • 分段和分页相结合。 先将用户程序分段每段内再划分成若干页,每段有段名(段号),每段内部的页有一连续的页号

  • 内存划分:按式存储管理方案

  • 内存分配:以为单位进行离散分配

  • 逻辑地址结构image-20230606112207652

    image-20230606112405725

  • 地址变换image-20230606112456678

  • 注:在段页式存储管理方式中,每访问一次数据, 需访问三次内存

    • 第一次访问内存中的段表
    • 第二次访问内存中的页表
    • 第三次访问相应数据
虚拟存储器
局部性原理
  • 时间局部性
    • 某条指令一旦执行,则不久以后该指令可能再次执行
    • 数据被访问过,则不久以后该数据可能再次被访问
    • 产生原因:是由于在程序中存在着大量的循环操作
  • 空间局部性
    • 程序访问了某个存储单元,在不久之后,其附近的存储单元也将被访问
    • 程序在一段时间内所访问的地址,可能集中在一定的范围之内
    • 产生原因:程序的顺序执行
虚拟内存
  • 进程运行时,先将要运行的部分程序装入内存,其他部分暂留外存

  • 当要执行的指令不在内存时,处理器发生中断,通知操作系统将所缺部分从外存调入内存,保证程序继续执行;

    • ➢ 当内存不足时,允许程序部分换入、换出
  • 虚拟内存的依据

    • 程序执行的局部性原理
  • 如何将程序划分成部分

    • 分页或分段
虚拟存储器
  • 是指具有请求调入功能和置换功能,能从逻辑上内存容量加以扩充的一种存储器系统
  • 其逻辑容量由内存容量和外存容量之和所决定
    • 受两个方面的限制:
      • 指令中表示地址的字长
        • 若CPU的有效地址长度为32位,则可以表示的地址最大空间为2^32,逻辑空间大小为4G,即虚存容量为 4GB。与物理空间的大小无直接关系
      • 外存的容量(对换区)
  • 运行速度接近于内存速度,而成本却又接近于外存
  • 主要特征
    • 多次性
      • 多次性是指一个作业被分成多次调入内存运行
    • 对换性
      • 对换性是指作业的运行过程中进行换进、换出。换进和换出能有效地提高内存利用率
    • 虚拟性
      • 虚拟性是指能够从逻辑上扩充内存容量,使用户所看到的内存容量远大于实际内存容量
请求分页系统
  • 它是在纯分页系统的基础上增加了请求调页页面置换两大功能所形成的页式虚拟存储系统

  • 硬件支持

    • 请求分页的页表机制
    • 缺页中断机构
    • 地址变换机构
  • 页表机制image-20230606125451769

  • 缺页中断机构image-20230606125729013

    image-20230606125738134

  • 地址变换机构image-20230606130109613

最小物理块数的确定

image-20230606130313368

image-20230606130331128

物理块的分配策略

image-20230606130545850

image-20230606130630443

image-20230606130634461

物理块的分配算法

image-20230606130713043

  • 平均分配算法image-20230606130745392
  • 按比例分配算法image-20230606130759297
  • 考虑优先权的分配算法image-20230606130811651
缺页率

image-20230606131741394

页面置换算法
最佳(优)置换算法(Optimal)
  • 从主存中移出永远不再需要的页面;如无这样的页面存在,则应选择最长时间不需要访问的页面
  • 过于理想化,难以实现
  • image-20230606132030021
先进先出置换算法(FIFO)
  • 本质:总是选择作业中驻留时间最长(即最老)的一页淘汰。即:先进入主存的页面先退出主存。
  • image-20230606140521798
  • image-20230606140532839
  • image-20230606140558270
  • Belady现象:在某些情况下会出现分配给的进程物理块数增多,缺页次数有时增加,有时减少的奇怪现象
最近最久未使用(LRU)置换算法

LRU(least Recently Used)

  • 它认为过去一段时间里不曾被访问过的页面,在最近的将 来可能也不会再被访问
  • 实质是:
    • 当需要置换一页面时,选择在最近一段时间内最久不用的页面予以淘汰
  • image-20230606141345896
三种算法缺页次数计算

image-20230606141752472

  • 存储块越多,缺页中断率越小?
    • image-20230606205156896
    • FIFO有随 着分给的页架数增加,缺页频率也增加的异常现象
最少使用置换算法LFU
  • 最少使用置换算法LFU(Least Frequently Used) 选择到当前时间为止被访问次数最少的页面被置换
  • 基本方法:
    • 记录每个页面的访问次数,最少访问的页面首先考虑淘汰
Clock置换算法
简单的Clock置换算法(NRU)

image-20230606205959091

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 扫描到内存中有该页面时,指针不会移动访问位置为1
改进型Clock置换算法
  • 首选最近没有被使用过的
  • 在驻留内存期间没有被修改过的页面作为被置换页面image-20230606210331520
  • image-20230606210521268
  • image-20230606210602739
缺页率对有效访问时间的影响
  • 设内存读写周期为t,查找快表时间为λ,缺页中断处理时间为ɛ

  • image-20230606211725208

  • CPU急剧下降的原因

    • : 进程调入一页,需将一页淘汰出去,刚淘汰出去的页马上要需要调入
  • 抖动

    • 如果系统花费大量的时间把程序和数据频繁地换入 和换出内存而不是执行用户指令,那么,称系统出 现了抖动。出现抖动现象时,系统显得非常繁忙, 但是吞吐量很低,甚至产出为零
    • 根本原因:选择的页面或段不恰当
    • 根据检测工作集的大小确定内存块的数量
  • 驻留集

    • 请求分页存储管理中给进程分配的物理块集合
  • 固定分配、可变分配、局部置换、全局置换image-20230608105752056

  • 三种置换策略 image-20230608110010639

    • 可变分配全局置换:
      • 只要缺页就分配新的物理块
    • 可变分配局部置换:
      • 根据缺页的频率来动态改变进程的物理块
    • 固定分配局部算法:
      • 就是告诉一个进程的物理块数不会改变
  • 何时调入页面image-20230608110215946

第五章 输入输出系统

四种 IO控制方式

使用轮询的可编程I/O方式
  • 程序I/O(Programmed I/O)方式,或称为忙 – 等待方 式。
  • 处理机向控制器发送一条IO指令启动输入设备输入数据时,同时把busy置为1,在不断循环测试busy
  • busy=0,完成输入,处理机读取数据,送入指定单元,完成一次IO
  • 对状态寄存器的忙/闲标志busy的检查实现控制image-20230609093334651
使用中断的可编程I/O方式
  • 中断驱动方式可以成百倍地提高CPU的利用率。
  • CPU与IO设备并行工作image-20230609093711208
直接存储器访问方式
  • DMA控制方式的引入
    • 为了进一步减少CPU对I/O的干预而引入了直接存储器访问方式
    • DMA控制方式的特点
      • 数据传输的基本单位是数据块,即在CPU与I/O设备之间,每次传送至少一个数据块
      • 所传送的数据是从设备直接送入内存的,或者相反
      • 仅在传送一个或多个数据块的开始和结束时,才需CPU干预,整块数据的传送是在控制器的控制下完成的
    • DMA方式较之中断驱动方式,又是成百倍地减少了CPU对 I/O的干预,进一步提高了CPU与I/O设备的并行操作程度
I/O通道控制方式
  • I/O通道方式是DMA方式的发展,它可进一步减少CPU的干预,即把对一个数据块的读(或写)为单位的干预减少为对一组数据块的读(或写)及有关的控制和管理为单位的干预

程序I/O方式

中断方式 :每“字节”传送产生一次中断。

直接存储器访问方式:数据块

通道方式 :一组数据块。通道是一种特殊的处理机

磁盘调度

提高磁盘IO速度的主要途径
  • 选择性能好的磁盘

  • 采用好的磁盘调度算法

  • 设置磁盘高速缓存

  • 采用高度可靠、快速的容量磁盘系统–磁盘冗余阵列

  • 数据的组织和格式image-20230609095403646

磁盘访问时间
  • 寻道时间Ts:指把磁臂(磁头)移动到指定磁道上所经历的时间

    • Ts=m×n+s
    • s:启动磁臂的时间
    • n:磁头移动n条磁道
    • m:移动每一条磁道所花费的时间
  • 旋转延迟时间Tτ

    • Tτ:指定扇区移动到磁头下面所经历的时间
    • 例如: 软盘旋转速度为 300 r/min或600 r/min,这样,平均Tτ 为50~100 ms。
    • 硬盘旋转速度为15000 r/min,每转需时4 ms,平均旋转延迟时间Tτ为2ms;
    • 1/2r r为转一圈所需要的时间
  • 传输时间Tt

    • Tt:指把数据从磁盘读出或向磁盘写入数据所经历的时间
    • Tt 的大小与每次所读/写的字节数b和旋转速度有关
      • Tt=b/N*r
      • r为转一圈所需要的时间;N为一条磁道上的字节数
先来先服务FCFS算法
  • 据进程请求访问磁盘的先后次序进行调度。此算法的优点是公平、简单,且每个进程的请求都能依次地得到处理,不会出现某一进程的请求长期得不到满足的情况。
最短寻道时间优先SSTF算法
  • 其要求访问的磁道,与当前磁头所在的磁道距离最近,以使每次的寻道时间最短
  • SSTF算法虽然能获得较好的寻道性能,但却可能导致某个进程发生“饥饿”现象
扫描(SCAN)算法
  • 优先考虑的是磁头当前的移动方向
  • 例如,磁头自里向外移动, 并同时自里向外地访问直至再无更外的磁道需要访问时,才将磁臂换向自外向里移动。(又常称之为 电梯调度算法 )
循环扫描(CSCAN)算法
  • CSCAN算法规定磁头单向移动,例如,只是自里向外移动, 当磁头移到最外的磁道并访问后,磁头立即返回到最里的欲访问磁道,亦即将最小磁道号紧接着最大磁道号构成循环,进行循环扫描。
缓存
引入缓存原因
  • 缓和CPU和IO设备间速度不匹配的矛盾
  • 减少对CPU的中断频率,放宽对CPU中断响应时间的限制
  • 解决数据粒度不匹配的问题
  • 提高CPU与IO设备之间的并行性

  • 缓冲如何提高IO速度
    • 减少物理IO
      • 从缓冲区中读取数据。这样可以减少对慢速设备的物理读取或写入操作次数,从而提高整体I/O速度
    • 批量操作
      • 缓冲可以将多个较小的I/O请求合并为一个较大的批量操作。
      • 通过减少操作系统和设备之间的上下文切换和管理开销,批量操作可以显著提高I/O速度
    • 异步I/O
      • 缓冲可以支持异步I/O操作,即应用程序可以发起I/O请求后立即继续执行其他任务,而不需要等待I/O操作完成
    • 数据预读和预写
      • 缓冲可以在应用程序请求数据之前,预先从设备中读取一定量的数据并存储在缓冲区中,当应用程序需要读取数据时,可以直接从缓冲区中获取
缓冲池
  • 缓冲区仅仅是一组内存块的链表

  • 而缓冲池是包含了一个管理的数据结构及一组操作函数的管理机制,用于管理多个缓冲区

  • 每个缓冲区由用于标识和管理的缓冲首部以及用于存放数据的缓冲体组成

    • 缓冲首部:
      • 缓冲区号,设备号,设备商的数据块号,同步信号量及队列链接指针
  • 三个队列

    • 空白缓冲队列emq
    • 输入队列inq
    • 输出队列outq
  • 四种工作缓冲区

    • 收容输入数据
    • 提取输入数据
    • 收容数出数据
    • 提取输出数据
Getbuf和Putbuf过程过程
  • 为了既要互斥又要同步
  • 对Addbuf(type,number), Takebuf(type)进行互斥和同步操作
    • 为每个队列设置一个互斥信号量MS(type)和一个同步信号量RS(type)
    • 实现Getbuf和Putbuf过程
  • 具体操作和生产者消费者类似 书p229
缓冲区处理I/O设备和CPU间的数据输送
  • 收容输入
    • 输入进程调用Getbuf(emq),把它作为收容输入工作缓冲区hin
    • 把数据输入其中,装满后调用Putbuf(inq,hin),将它挂在输入队列inq上
  • 提取输入
  • 收容输出
  • 提取输出
  • image-20230615172655144
SPOOLing技术的组成,如何利用SPOOLing技术实现共享打印机
  • 组成
    • 输入输出队列
      • 用于存储待处理的输入输出任务,例如打印任务、磁盘操作等。这些任务按照先后顺序排队等待执行。
    • 输入输出缓冲区
      • 用于临时存储输入输出数据。当数据从输入设备读取或写入输出设备时,首先将数据存储在缓冲区中,然后由SPOOLing系统进行处理
    • SPOOLing守护进程
      • 是运行在后台的特殊进程,负责管理输入输队列和缓冲区
    • 输入/输出设备驱动程序
      • 与具体的输入/输出设备相关的驱动程序。它们负责实际的输入/输出操作,将数据从缓冲区传输到设备或从设备读取数据。
  • 共享打印机的实现
    • 1.创建一个共享打印机队列:将所有需要打印的文件按顺序加入到打印机队列
    • 2.SPOOLing系统将打印队列中的文件逐个分配给打印机进行打印
    • 3.当文件分配给打印机时,SPOOLing系统将文件从磁盘读取到输入缓冲区
    • 4.打印机驱动程序从输入缓冲区获取数据,并将其发送到打印机进行打印
    • 5.打印完成后,打印机驱动程序将打印机状态通知给SPOOLing系统
    • 6.SPOOLing系统从打印队列中移除已完成的文件,并将下一个文件分配给打印机

第六章 文件系统

文件的逻辑结构

image-20230609125801526

顺序分配
  • 连续分配
    • 要求为每一个文件分配一组相邻接的盘块
    • 一组盘块的地址定义了磁盘上的一段线性地址
    • 逻辑上相邻的块在物理上也相邻
  • 文件目录中为每个文件建立一个表项FCB,其中记载文件的第一个数据块地址及文件长度image-20230610220224286
  • 对于顺序文件,连续读/写多个数据块内容时,性能较好
  • 连续分配的优点
    • 顺序访问容易
      • 可以随机存取, 能很快检索文件中的一个数据块
      • 例如,如果一个文件的第一个数据块的序号为x,需要检索文件的第y块,则该数据块在外存中的位置为x+y-1
    • 顺序访问速度快
      • 磁头移动距离短,效率最高
  • 连续分配存在的问题
    • 要求有连续的存储空间
      • 该分配方案可能会导致磁盘碎片,严重降低外存空间的利用率
      • 不方便拓展
      • 解决方法之一,系统定期或不定期采用紧凑技术,将小分区合并为大的、连续分区,将文件占用空间合并在一起
    • 必须事先知道文件的长度
      • 空间利用率不高
      • 不利于文件尺寸的动态增长
  • 只有顺序存储定长记录顺序结构文件才能实现随机存取image-20230610214154340
链接分配
  • 采用链接分配方式时,可通过在每个盘块上的链接指针,将同属于一个文件的多个离散的盘块链接成一个链表,把这样形成的物理文件称为链接文件

  • 隐式链接

    • 在文件目录的每个目录项中,都须含有指向链接文件第一个盘块和最后一个盘块的指针
    • 每个盘块中都含有一个指向下一个盘块的指针
    • 读入逻辑块号i,操作系统需要依次读入0至i-1号逻辑块
    • 只支持顺序访问,不支持随机访问,因为指向下一个逻辑块号的指针在上一个逻辑块号中
    • 方便文件拓展image-20230610221338433
  • 显式链接

    • 把用于链接文件各个物理块的指针显式的存放在内存的一张链接表中
    • 整个磁盘仅设置一张文件分配表 FATimage-20230610221609515
    • 在FAT中,凡是属于某一文件的第一个盘块号, 均作为文件地址被填入相应文件的FCB 的“物理地址”字段中
      • 开机时,FAT读入内存并且常驻内存
    • 查找记录的过程是在内存中进行的,因而不仅显著地提高了检索速度,而且大大减少了访问磁盘的次数
    • 所有盘块号都在文件分配表FAT中
  • 链接分配的优点

    • 无外部碎片,没有磁盘空间浪费
    • 无需事先知道文件大小。文件动态增长时,可动态分配空闲盘块。对文件的增、删、改十分方便
    • 查找记录过程是在内存中进行的大大提高了检索速度减少了访问磁盘的次数
  • 缺点

    • 不能支持高效随机/直接访问,仅适合于顺序存取
    • 需为指针分配空间。(隐式链接)
    • 可靠性较低(指针丢失/损坏)
    • 文件分配表FAT(显式链接) FAT需占用较大的内存空间
索引分配

(33条消息) 操作系统——文件的索引分配_混合索引_秋之颂的博客-CSDN博客

  • 采用索引文件结构的文件需要在自己的FCB中记录自己的索引块在磁盘中是哪一块

    • 每个文件都有自己的索引表
      • 注意:显示链接中一个文件分配表FAT是一个磁盘对应一张
  • 索引表就是一个含有许多盘块号的数组

  • 单级索引分配

    • 优点
      • 索引分配方式支持直接访问。当要读文件的第i个盘块时, 可以方便地直接从索引块中找到第i个盘块的盘块号;
      • 基于数据块的分区能消除外部碎片
      • 容易实现文件的扩展
    • 缺点
      • 大文件索引项较多,可能使一个数据块容纳不了一个文件的所有分区的索引
      • 索引块可能要花费较多的外存空间。每当建立一个文件时,便须为之分配一个**专门的索引块,**将分配给该文件的所有盘块号记录于其中。对于小文件如果采用这种方式,索引块的利用率将是极低的
  • 多级索引分配

    • FCB记录顶级索引块的磁盘号
    • 顶级索引块没有调入内存时:查询n层索引结构n+1次读磁盘操作
    • 此时,应为这些索引块再建立一级索引,形成两级索引 分配方式
    • image-20230609131536030

image-20230618121516032

  • 混合索引方式
    • 每个文件的索引表 为13个索引项。最前面 10项直接登记存放文件信息的物理块号(直接寻 址) 如果文件大于10块,则利用第11项指向一个 物理块,假设每个盘块大小为4KB,每个盘块号 占4个字节,该块中最多可放1K个盘块号(一次 间接寻址)。对于更大的文件还可利用第12和第 13项作为二次和三次间接寻址image-20230609132111765
    • image-20230610223755276
总结

image-20230610223959999

  • 有结构文件的逻辑结构
顺序文件
  • image-20230615201041319
索引文件
  • 每个文件建立一张索引表,每个索引表的表项对应文件的一条记录
    • 文件的记录可以在物理上离散的存放
    • 索引表的表项必须顺序存放
    • 索引表的表项定长
    • 所以索引表本身是定长记录的顺序文件
    • 将关键字作为索引号内容,按关键字顺序排列,则可以支持按照关键字折半查找
  • 可以建立多个索引表image-20230615201424943
索引顺序文件
  • 还是会建立索引表,但是不会为每个记录建立一个索引表项。
    • 而是为每个记录分组,每个分组对应一个索引表项
  • 索引表不需要按照关键字排序,方便插入和删除
  • image-20230615201717552
  • 把记录平均分组,大大提升了查询速率image-20230615201829494
  • 多级索引顺序文件image-20230615201929107

文件存储空间的管理方法

空闲分区表
  • 空闲表法属于连续分配方式,它为每个文件分配一块连续的存储空间,即系统也外存上的所有空闲区建立一张空闲表,每个空闲区对应于一个空闲表项,其中包括表项序号、该空闲区的第一个盘块号、该区的空闲盘块数等信息image-20230609142558177

  • 适合于可变大小分区的连续分配方式

空闲链表法
  • 用专门的空闲分区表登记空闲分区信息会浪费一定的存储空间,而且不适合登记分散且数目很多的空闲分区,不利于基于存储块的链接文件和索引文件的存储空间分配

  • 空闲链表法是将所有空闲盘区拉成一条空闲链。根据构成链所用基本元素的不同,可把链表分成两种形式:

    • 空闲盘块链
    • 空闲盘区链
  • 空闲盘块链

    • 将磁盘上的所有空闲空间,以盘块为单位拉成一条链
    • 当用户因创建文件而请求分配存储空间时,系统从链首开始,依次摘下适当数目的空闲盘块分配给用户
    • 当用户因删除文件而释放存储空间时,系统将回收的盘块依次插入空闲盘块链的末尾
  • 空闲盘区链

    • 为了提高对空闲盘区的检索速度,可以采用显式链接方法,亦即,在内存中为空闲盘区建立一张链表
    • 每个分区结点内容:起始盘块号、盘块数、指向下一个空闲盘区的指针
    • 问题
      • 一段时间以后,可能会使空闲分区链表中包含太多小分区,使文件分配到的存储空间过分离散
      • 删除一个由许多离散小分区组成的文件时,将回收的小分区链接到空闲分区链表中需要很长时间
      • ▪若一个文件申请连续存储空间,则需要花费较长的时间查找相邻的空闲分区
    • 这种空闲空间组织方法适合于非连续存储文件
成组链接方式

(34条消息) 操作系统——成组链接法_LengDanRan的博客-CSDN博客

文件目录

  • 文件目录:

    • 文件控制块FCB的有序集合
  • 对目录进行的操作

    • 搜索:
      • 当用户要使用一个文件时,系统根据文件名搜索文件目录,找到该文件对应的目录项
    • 创建文件:
      • 创建一个新的文件时,需要在其所有的目录中增加一个目录项
    • 删除文件:
      • 删除一个新的文件时,需要在其所有的目录中删除项
文件目录管理要求
  • 对目录管理的要求:
    • 实现"按名存取"
    • 提高对目录的检索速度
    • 文件共享
    • 允许文件重名
文件控制块FCB
  • 用于描述和控制文件的数据结构,存放了文件的有关说明信息,记录了系统对文件进行管理所需要的全部信息
  • 文件由FCB和文件体(文件本身)两部分组成。
  • FCB是文件存在的标志
  • FCB保存在文件目录中,一个FCB就是一个目录项
  • 文件控制块FCB的内容
    • 文件名、物理地址
    • image-20230610113351841
  • 文件目录
    • 把所有的FCB组织在一起,就构成了文件目录, 即文件控制块的有序集合
  • 目录项
    • 构成文件目录的项目
    • 目录项就是FCB
  • 目录文件
    • 为了实现对文件目录的管理,通常将文件目录以文件的形式保存在外存,这个文件就叫目录文件

目录结构

单级目录结构
  • 所有用户的全部文件目录保存在一张目录表中,每个文件的目录项占用一个表项image-20230615193833683
  • 优点:
    • 实现简单
    • 能实现目录管理的基本功能:按名存取
  • 缺点
    • 查找速度慢
    • 不允许重名
    • 不便于实现文件共享
两级目录结构
  • 整个系统中建立两级目录
    • 为每个用户建立一个单独的用户文件目录(UFD)
    • 系统中为所有用户建立一个主文件目录(MFD)

image-20230615194304713

  • 优点:
    • 一定程度解决了重名问题
    • 提高了文件目录检索效率
    • 简单的文件共享
  • 缺点:
    • 不便用户文件的逻辑分类;进一步解决重名、共享、检索效率等问题
多级目录结构
  • 多级目录结构又称为树型目录结构,主目录在这里被称为根目录,把数据文件称为树叶,其它的目录均作为树的结点
  • image-20230615194530965
  • 路径名:
    • 从树的根开始,把全部目录文件名与数据文件名依次用/连接起来。即构成该数据文件的路径名(path name)
  • 系统中的每一个文件都有惟一的路径名
  • 不便于实现文件目的共享
增加目录
  • 在用户要创建一个新文件时,只需查看在自己的UFD及其子目录中,有无与新建文件相同的文件名。若无,便可在UFD或其某个子目录中增加一个新目录项。
删除目录
  • 不可删除非空目录
  • 可删除非空目录

Shell编程

什么是shell

  • shell是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行
  • Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核

image-20230611154247742

image-20230614112955159

读shell程序
  • image-20230614113708936
  1. #!/bin/sh: 声明脚本使用的解释器是/bin/sh,即Shell解释器。
  2. if [ $# -ne 1 ]: 检查命令行参数的数量是否为1。$#表示命令行参数的数量,-ne表示不等于。
  3. then: 如果上一条命令的结果为真(即命令行参数数量不等于1),则执行接下来的命令。
  4. echo "Usage: $0 filename" >&2: 输出错误信息到标准错误输出。$0表示脚本的名称,>&2表示将输出重定向到标准错误输出。
  5. exit 1: 退出脚本并返回状态码1,表示发生错误。
  6. count=1: 初始化变量count为1,用于保存行号。
  7. cat $1 | while read line: 使用cat命令读取指定文件$1的内容,并通过管道传递给后面的while循环逐行处理。
  8. echo $count $line: 输出行号和当前行的内容。
  9. count=expr $count + 1``: 使用expr命令对count进行加1操作,更新行号。
  10. done > tmp$$: done表示循环结束,> tmp$$将循环输出重定向到一个临时文件tmp$$中。
  11. mv tmp$$ $1: 使用mv命令将临时文件tmp$$重命名为原始文件$1,覆盖原始文件,从而实现给每行添加行号的效果。

该脚本的执行流程是先检查命令行参数数量,如果不等于1,则输出错误信息并退出。然后,初始化行号变量count为1,通过cat命令读取文件内容,并使用while循环逐行处理。循环内部输出行号和行内容,并更新行号。最后,将带有行号的内容写入临时文件,并使用mv命令将临时文件重命名为原始文件,完成添加行号的操作。

输入重定向

$ cat ↙ cat命令后无文件名, cat等待键盘输入

abcde

abcde 键盘输入内容

this is a test line

this is a test line cat进程输出内容

Ctrl+d

$

  • cat命令的输入来自标准输入文件(键盘),ctrl+d结束键盘输入img
  • cat后有文件名
    • t进程的输入不是来自命令行参数,而是来自重定向文件abc
    • cat进程的输出送到标准输出荧光屏上

$ cat < abc

aaaaaaaaaaaaaaa

bbbbbbbb

cccccccccccccccccc

$

常见的输入输出重定向形式

image-20230611161637186

标准错误输出重定向

command 2> filename ( 2和>之间没有空格 )

  • image-20230611162615199
  • image-20230611162644895
  • 把标准输出和标准错误输出都定向到一个文件中image-20230611162939599
ls-l
  • image-20230614123957812

管道

  • 管道用于连接两个命令, 它把前一个命令的标准输出重定向给后一个命令作为标准输入, 其格式为

    command1 | command2

echo

  • echo命令的基本功能就是在标准输出上显示后面的字符串,或变量的值。当字符串中带空白符或其它控制字符时,用引号将其括起来。例如

$ echo 12345

12345

$ echo “department computer”

department computer

$ echo “My home directory is: $HOME”

My home directory is: /usr/teacher/david

$ echo –n “Input your choice (y/n) [ ]\b\b”

Input your choice (y/n) [ _ ]

系统变量

$0 当前shell程序的名字

$1 ~ $9 命令行上的第一到第九个参数

$# 命令行上的参数个数

$* 命令行上的所有参数

$@ 分别用双引号引用命令行上的所有参数

$$ 当前进程的进程标识号(PID)

$? 上一条命令的退出状态

$! 最后一个后台进程的进程标识号

$ echo aa bb cc dd $$

aa bb cc dd 2391

$ cat file1 file2 > file3 2> errlog

$ echo $? (非0表示命令运行失败, 错误信息在 errlog 文件中)

$ echo

                                    (空行, 即echo输出串尾隐含的换行符)

$ echo This is a test. (单词间多个空格)

This is a test.

$ echo “This is a test.” (用引号包括时结果如何?)

  • 系统变量只能引用不能修改

局部变量

  • 局部变量是由用户根据需要任意创建的. 变量名通常由一个字母后跟零个到多个字母、数字或下划线组成。引用变量的值时,在变量名前面加上$符号. 例如:

$ AA=123 定义变量AA

$ echo $AA 引用变量AA的值

123 (变量AA的值)

$ B=“this is a string” 定义变量B, (字符串中有空格时用引号)

$ echo $B 引用变量B的值

this is a string (变量B的值)

单双引号、反撇号、花括号

$ a=“he is a student”

$ echo “She said: $a”

She said: he is a student echo执行时,替换了变量$a的值

$ b=‘The value of a is $a’

$ echo $b

The value of a is a e c h o 执行时,未替换了变量 a echo执行时,未替换了变量 aecho执行时,未替换了变量a的值

  • 双引号替换、单引号不替换

$ a=date

$ echo $a

date (变量a的值是字符串date)

$ b=date (反撇号中的字符串作为命令名)

$ echo $b

Sat Feb 1 16:28:19 Beijing 2003

(变量b的值是反撇号中命令的执行结果)

$ c=“There is a teach”

$ echo “$cer reading room”

reading room (未定义变量cer, 其值用空串替代)

$ echo “${c}er reading room”

There is a teacher reading room

(花括号将变量名和后面的字符串区分开)

  • 未定义的变量名用空串代替
  • 花括号将变量名和后面的字符串区分开

进程及进程状态

  • 进程的生命周期
    • 创建运行等待运行…等待运行结束
  • 生命周期的三种状态
    • 运行态
      • 进程正在占用CPU和其他资源进行运算
    • 就绪态
      • 进程已经做好了一切准备,等待获得CPU投入运行
    • 睡眠态
      • 进程因等待输入输出或其它系统资源, 而让出CPU资源, 等待运行条件满足
PS 获取进程状态信息

不带参数的ps命令运行时, 显示该用户当前活动进程的基本信息

$ ps
 PID          TTY        TIME        COMMAND
 612           tty08        0:37           sh
 931           tty08        0:01           ps
 $

PID 进程标识号. 系统每个进程在其生命周期都有一个唯一的PID.

TTY 启动该进程的终端号

TIME 进程累计占用CPU的时间

COMMAND 产生该进程的命令

ps -e (或-a) 显示系统中所有活动进程的信息

$ ps -e
PID TTY TIME COMMAND
0 ? 0:00 swapper
1 ? 0:01 init
358 00 0:01 sh
695 01 0:01 sh
23 ? 0:00 logger
732 03 0:00 vi
25 ? 0:00 cron
681 02 0:00 getty
623 03 0:01 csh
732 01 0:01 ps
$

ps-f 显示该进程的所有信息

$ ps -f
UID PID PPID C STIME TTY TIME COMMAND
liu 298 1 0 14:57:02 02 0:02 sh
liu 395 298 16 16:31:19 02 0:00 ps-f

  • 其中
    • UID 进程所有者的用户标识数
    • PID 进程标识数
    • PPID 本进程的父进程标识数
    • C 进程调度参数, 反映本进程使用CPU的状况
    • STIME 进程的启动时间
    • TTY 启动进程的终端号
    • TIME 进程累计占用CPU的时间
    • COMMAND 启动该进程的命令名
sleep暂停进程运行

$ sleep 5
[进程暂停5秒钟, 什么也不作]
$

$ sleep 10; who
[进程暂停10秒钟后, 显示系统中登录的用户名]

$ echo “I am sleeping…”; sleep 100; echo “I am awake”
I am sleeping … [等待100秒钟]
I am awake
$

  • who : 显示系统中登录的用户名
kill 终止进程运行
  • 三种情况下进程被终止

    • 进程运行完成自动消亡
    • 用户按^c 或 Del 等中断键, 强行终止前台进程的运行
    • 用户发出 kill 命令, 强行终止后台进程或键盘锁住了的前台进程的运行
  • kill命令的三种常用格式

      kill         PID

      正常结束进程, 自动完成所有善后工作, 作用类似于按 Del 键.

      kill   -1   PID

      先挂起该进程, 终止子进程, 完成善后工作, 再终止该进程.

      kill   -9   PID

      立即强行终止该进程, 不作任何善后工作.  可能出现资源浪费和"孤儿"进程.

shell编程

三步基本过程
  • 建立shell文件
    • 包含任意多行操作系统命令或shell命令的文本文件
  • 赋予shell文件执行权限
    • chmod命令修改权限
  • 执行shell文件
    • 直接在命令行上调用该shell程序
实例
  • 1建立shell文件

$ cat prog1

who | grep $1

  • 2赋予执行权限(初始文本文件无执行权限)

chmod 740 prog1

  • 3执行该shell程序

$ prog1 student5

prog1: not found

(shell在标准搜索目录中找不到prog1命令)

常用的功能性命令

read
  • read从标准输入读入一行, 并赋值给后面的变量
  • 如果执行read语句时标准输入无数据, 则程序在此停留等侯, 直到数据的到来或被终止运行

. read var

        把读入的数据全部赋给var

. read var1 var2 var3

        把读入行中的第一个参数赋给var1, 第二个参数赋给var2, ……,把其余所有的参数赋给最后一个变量.
   read    读取标准输入(键盘), 输入的内容赋给后面的变量.
   1.

   $ read  name   age
   yilan   23               从键盘输入的内容
   $ echo  "student  $name  is  $age  years  old"
   student  yilan  is  23  years old           屏幕显示的内容

   2.

   echo  -n "Input  your  name: "
   read  username
   echo  "Your name is  $username"

   3.

   #example2  for  read
   echo –n  "Input  date  with  format  yyyy  mm dd: "
   read  year  month  day
   echo  "Today  is  $year/$month/$day,  right?"
   echo  -n "Press  any  key  to  confirm  and  continue"
   read  answer
   echo "I  know  the  date,  bye!"
expr 命令
  • 算术运算命令expr主要用于进行简单的整数运算,包括加(+)、减(-)、乘(*)、整除(/)和求模(%)等操作。例如

$ expr 12 + 5 * 3 #反斜线去掉*号的元字符含义
27
$ expr 3 - 8 / 2
-1
$ expr 25 % 4
1
$ num=9
$ sum=expr $num \* 6 #反撇号引用命令的运行结果
$ echo $sum
54

if else等
  • 语法结构:

    •      if    表达式
           then  命令表
           fi     
      
  • shell程序prog2, 测试命令行参数是否为一个已存在的文件或目录。 用法为:

    • ​ prog2 file
    • prog2脚本内容入:

    #The statement of if…then…fi (注释语句)
    if [ -f $1 ] (测试命令行第一个参数是否为文件)
    then
    echo “File $1 exists” (引用变量值)
    fi
    if [ -d $HOME/$1 ] (测试参数是否为目录)
    then
    echo “File $1 is a directory” (引用变量值)
    fi

    • 执行prog2

    $ prog2 prog1
    File prog1 exists
    $0为prog2; $1为prog1, 是一个已存在的文件.
    $ prog2 backup
    File backup is directory
    $0为prog2; $1为backup,是一个已存在的目录.

概念总结

外部碎片和内部碎片

  • 外部碎片是内存中没有被分配的单元
  • 内部碎片是分配的单元中没有被使用的部分

基本分页

  • 内存分为页框
    • 也叫内存块,物理块
  • 进程分页
    • 也叫**页面 **
  • 页表是一个数据结构,一般存放在PCB中,调用时放入内存
    • 一个进程对应一个页表
    • 进程的每一个页面对应一个页表项
      • 页表项就是页表中的一行
      • 页表项包含页号和块号
页表项占多少字节
  • 计算块号所需字节数image-20230606214027291
  • 页号是不需要占存储空间的
    • 因为物理块号在内存中是连续存放的,所以页号可以隐含image-20230606214211733
  • 总结:
    • 一个页表项在逻辑上包含页号和块号
    • 在物理上只用包含块号,只有块号需要占用存储空间
    • 内存块的起始地址:块号内存块大小
地址转换
  • 确定逻辑地址A对应的页号

  • 根据页号查询页表,找到在内存中的起始地址

  • 确定逻辑地址A的页内偏移量W

  • 如果有k为表示页内偏移量,则说明一个系统中一个页面的大小有2^k个内存单元

  • 如果有m为表示页号,则说明一个系统中一个页面的大小有2^m个页面

  • 即页面大小和页内偏移量位数可以相互转换

页表寄存器PTR
  • 当进程调度时,操作系统将页表在内存中的起始地址F页表长度M放入PTR中

    • M:进程中有M个页表项
  • 页式管理中地址是一维的,只要知道了一个逻辑地址,就可以自动算出页号、页内偏移量

  • 注意:会产生页内碎片,下一个页表项存放地址不能使用、

    • 为了方便查询,会让页表项占更多字节,刚好装得下整数个页表项
快表TLB
  • 高速缓存,存放页表项的副本。不是内存
  • 页表存放在内存中,称为慢表

image-20230618192932632

两级页表
  • 页表进行分组每个物理块刚好可以放入一个分组。再将各个内存块离散的分配到内存块中
  • 另外,为离散分配的页表再建立一张页表,称为外层页表、页目录表或者顶层页表
  • image-20230606233726241
    • 页目录表中存放的是二级页表的页号二级页表在内存中的物理块号

image-20230606234147051

  • 注意:多级页表机制中,各级页表的大小不能超过一个页面image-20230606234523777
    • 上题必须要三级页面
  • 访存问题:
    • n级页表无快表时:n+1次

基本分段

段表:
  • 作用和页表类似,存放段号、段长和基址

  • 段表项长度相同,段号可以隐藏

  • image-20230608084601481

地址变换
  • 与页式管理系统不同的是:需要检查段内地址是否超过段长,因为每个段段长不一样
  • image-20230608085422052

分段和分页的对比

  • 分页的地址空间是一维的,一个记忆符即可表示
  • 分段的地址空间是二维的,标识一个地址时,既要给出段名,也要给出段内地址image-20230608085904475
  • 分段更容易实现信息的共享和保护。仅需让两个进程的段表中段长相同,基址相同即可
  • 访问一个逻辑地址需要几次访存
    • 分页(单级页表):第一次访问内存中的页表,第二次访问目标内存单元
    • 分段:第一次访问内存中的段表,第二次访问目标内存单元

段页式

分段分页优缺点
  • 分页:
    • 内存空间利用率高,不会产生外部碎片, 只会有少量的页内碎片
    • 不方便按照逻辑模块实现信息的共享保护
  • 分段
    • 方便按照逻辑模块实现信息的共享保护
    • 会产生外部碎片
段页式管理
  • 先分段,再分页

    • 段内地址被再划分为页号和页内偏移量
  • 段号的位数决定了每个进程最多可以分为几个段

  • 页号的位数决定了每个段最大有多少页

  • 页内偏移量决定了页面大小、内存块大小image-20230608091652009

  • 段表

    • 每个段表项由段号、页表长度和页表存放块号(页表起始地址)组成。
    • 每个段表项长度相等,段号是隐含的
    • 与段式管理中的段表结构不同image-20230608092614922
  • 页表

    • 页号和内存块号
  • 一个进程对应一个段表,每个段,每个段对应一个页表。

  • 地址转换image-20230608093353292

考点

分析题

处理机调度分为哪三级?再描述从装入一个作业开始到执行此作业的整个详细的调度过程
  • 调度分为:
    • 高级调度
    • 低级调度
    • 中级调度
  • 中级
    • 高级调度(作业调度)将外存上的作业调入内存
    • 然后为此作业创建进程PCB,并将其加入就绪队列中
    • 启用低级调度,若调度程序根据一定调度算法选择此进程执行则开始执行此作业,从而完成整个作业的调度过程
主存储器容量为8MB,虚存容量为2GB,虚地址和物理地址各为多少位?根据寻址方式计算出来的有效地址是虚拟地址还是物理地址?如果页面大小为4kB,页表长度是多少
  • 虚地址:31位(2GB=2^31)
  • 物理地址:23位(8MB=2^23)
  • 根据寻址方式计算出来的有效地址是物理地址
  • 页表长度:231/212=219,故19位
如果采用基于优先级可抢占的调度机制,请问在哪些情况下需要启动调度程序?也就是调度时机有哪些?至少说出4种
  • 调度时机
    • 一个新进程被创建,并进入就绪队列
    • 当前执行进程因为I/O被阻塞
    • 当前执行进程挂起自己
    • 当前执行进程调用exit,return等函数退出执行
    • 一个阻塞进程被唤醒后
    • 一个挂起进程被激活后
  • 总结:当进程释放CPU的时候,或者就绪队列进入新进程的情况(新进程可能是也优先级更高的进程,所以需要启动调度程序)
论述操作系统中的系统调用函数是如何实现的?
  • 系统调用通过软终断实现
  • 操作系统初始化过程中会产生一张中断向量表,其中保存了中断服务程序的入口地址,发生软终断后通过中断号找到对应的中断服务程序
  • 从而找到注册到操作系统的服务系统调用的调用函数,完成系统调用
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值