• 【操作系统】常用总结


    基础知识

    操作系统

    操作系统(Operation System, OS)是管理和控制计算机硬件与软件资源的计算机程序,是直接运行在“裸机”上的最基本的系统软件,任何其他软件都必须在操作系统的支持下才能运行。

    • 操作系统是计算机系统资源的管理者,分为:
      • 处理机管理
      • 存储器管理
      • 设备管理
      • 文件管理
    • 操作系统是用户计算机硬件系统之间的接口,同时也是计算机硬件其他软件的接口,分为:
      • 命令接口
      • 程序接口
    • 功能:
      • 管理计算机系统的硬件、软件及数据资源;
      • 控制程序运行;
      • 改善人机界面;
      • 为其他应用软件提供支持,让计算机系统所有资源最大限度地发挥作用;
      • 提供各种形式的用户界面,使用户有一个好的工作环境;
      • 为其他软件的开发提供必要的服务和相应的接口等。
    • 特征:
      • 并发:两个或者多个事件在同一时间间隔内发生;
      • 共享:系统中的资源可供内存中多个并发执行的进程共同使用;
      • 虚拟:把一个物理上的实体变为若干个逻辑上的对应物;
      • 异步:在多道程序环境下,允许多个程序并发执行,但因资源有限,进程的执行不是一贯到底,而是走走停停,以不可预知的速度向前推送,这就是进程的异步性。

    基本概念

    • 互斥:进程之间访问临界资源时相互排斥的现象;

      临界资源:一次仅允许一个进程使用的资源,如 打印机。
      临界区:每个进程中访问临界资源的那段代码。

    • 并发:同一时间段有几个程序都处于已经启动到运行完毕之间,并且这几个程序都在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。并发的两种关系是同步和互斥;
    • 并行:单处理器中进程被交替执行,表现出一种并发的外部特征;在多处理器中,进程可以交替执行,还能重叠执行,实现并行处理,并行就是同时发生的多个并发事件,具有并发的含义,但并发不一定是并行,也就是说事件之间不一定要同一时刻发生;
    • 同步:进程之间存在依赖关系,一个进程结束的输出作为另一个进程的输入。具有同步关系的一组并发进程之间发送的信息称为消息或者事件;
    • 异步:和同步相对,同步是顺序执行,而异步是彼此独立,在等待某个事件的过程中继续做自己的事,不要等待这一事件完成后再工作

      线程是实现异步的一个方式,异步是让调用方法的主线程不需要同步等待另一个线程的完成,从而让主线程干其他事情。

    • 多线程:多线程是进程中并发运行的一段代码,能够实现线程之间的切换执行;

      异步和多线程:不是同等关系,异步是目的,多线程只是实现异步的一个手段,实现异步可以采用多线程技术或者交给其他进程来处理。

    发展历程

    • 手工阶段
    • 单道批处理系统
    • 多道批处理系统
    • 分时操作系统
    • 实时操作系统
    • 网络操作系统和分布式操作系统

      网络操作系统和分布式操作系统的不同之处在于:
      在分布式操作系统中,若干台计算机相互协同完成同一任务;
      而在网络操作系统中,每台计算机都是相互独立的,它们并不能相互协同完成同一任务。

    CPU的工作状态

    大多数计算机系统将CPU执行状态分为目态管态
    管态就是 supervisor(管理者) mode 翻译来的。
    那么目态呢,其实是 object(目标) mode 翻译来的。

    • 管态:supervisor(管理者) mode 又叫特权态、系统态或者核心态。CPU在管态下可以执行指令系统的全集。

      如果程序处于管态,则该程序就可以访问计算机的任何资源,即 它的资源访问权限不受限制。

      通常,操作系统在管态下运行。

    • 目态:object(目标) mode又叫常态或用户态。机器处于目态时,程序只能执行非特权指令,不能直接使用系统资源,也不能改变CPU的工作状态,并且只能访问这个用户程序自己的存储空间。

      科普:为什么叫 object mode 呢?
      通常CPU执行两种不同性质的程序:一种是操作系统内核程序;另一种是用户自编程序或系统外层的应用程序
      对操作系统而言,这两种程序的作用不同,前者是后者的管理者,因此“管理程序”要执行一些特权指令,而“被管理程序”出于安全考虑不能执行这些指令。
      因为管理者需要管理它,它就是管理者的管理目标。所以就叫 object mode

    • 目态(用户态)→管态(核心态)
      • 系统调用:这是用户态进程主动要求切换到核心态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。
        系统调用机制的核心是使用了操作系统为用户开放的一个中断来实现。
      • 异常:当 CPU 在执行用户态程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了核心态,如 缺页异常。
      • I/O设备的中断:当 I/O 设备完成用户请求操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令,转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到核心态的切换。

        例如,硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中,执行后续的操作。

    其中,系统调用可以认为是用户进程主动发起的,异常外部设备中断则是被动的。

    管理功能

    • 处理机管理:
      • 进程控制:在传统多道程序环境中,要是作业运行,必须先为它创建一个或多个进程,并为之分配必要的资源。当进程运行结束后,立即撤销该进程,以便能及时回收该进程所占用的各类资源。
      • 进程同步:为多个进程(含线程)的运行进行协调。
        • 进程互斥方式:进程(线程)在对临界资源进行访问时,应采用互斥方式。
        • 进程同步方式:在相互合作去完成共同任务的诸进程(线程)间,由同步机构对它们的执行次序加以协调。
      • 进程通信:在多道程序环境下,为了加速应用进程的运行,应在系统中建立多个进程,并且再为一个进程建立若干个线程,由这些进程(线程)相互合作去完成一个共同的任务,而在这些进程(线程)之间又往往需要交换信息。
      • 调度:在后备队列上等待的每个作业或者进程,通常都需要调度才能执行,调度的任务,即 将处理机分配给它。
    • 存储器管理:
      • 内存分配:采用静态和动态两种方式实现内存分配数据结构,以记录内存使用情况,按照一定算法分配,对不再需要的内存进行回收。
      • 内存保护:确保每道用户程序都只在自己的内存空间运行,彼此互不干扰。
      • 地址映射:编译后的程序的地址分为逻辑地址和物理地址,多道程序环境中,每道程序不可能都从 “0” 地址开始,要保证程序运行,则须将逻辑地址转换成内存空间中的物理地址。

        动态重定位:在程序执行过程中,每当访问指令或数据时,将要访问的程序或数据的逻辑地址转换成物理地址

        实现方法:在系统中增加一个重定位寄存器,用来装入程序在内存中的起始地址,程序执行时,真正访问的内存地址是相对地址与重定向寄存器中的地址相加之和,从而实现动态重定位。

      • 内存扩充:从逻辑上去扩充内存容量,使用户所感受到的内存容量比实际容量大得多,或者让更多的程序能并发执行。
    • 设备管理:
      • 缓冲管理:缓冲区机制能够有效缓解 CPU 运行的高速性和 I/O 低速性的矛盾。
      • 设备分配:设置设备控制表、控制器控制表等数据结构,能够了解指定设备当前是否可用,是否忙碌,以及该设备被分配出去,系统是否还安全。
      • 设备处理程序:实现 CPU 和设备管理器之间的通信,由 CPU 向设备控制器发出 I/O 命令,要求它完成指定的 I/O 操作,反之由 CPU 接收从控制器发来的中断请求,并给予迅速的响应和相应的处理。
    • 文件管理:
      • 文件存储空间的管理:由文件系统对诸多文件及文件的存储空间实施统一的管理,对每个文件分配必要的外存空间,提高外存的利用率和文件系统的执行速度。
      • 目录管理:相当于文件的索引,建立目录项(文件名、文件属性、文件在磁盘中的物理位置等),方便用户查询检索。
      • 文件的读/写管理和保护:防止未经批准的用户存取文件、防止冒名顶替存取文件、防止以不正确的方式使用文件。

    进程与线程

    对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个 Word 就启动了一个 Word 进程。
    有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)

    类比:
    进程 = 工厂
    线程 = 工厂里各个流水线

    进程

    进程可以认为是程序执行时的一个实例。进程是系统进行资源分配的独立实体,且每个进程拥有独立的地址空间。(即 资源的分配和调度的一个独立单元
    进程控制块(Process Control Block, PCB):保存运行期间进程的数据,PCB进程存在的唯一标志

    • 进程 = 程序 + 数据 + PCB
    • 一个进程无法直接访问另一个进程的变量和数据结构,如果希望让一个进程访问另一个进程的资源,需要使用进程间通信,比如:管道、文件、套接字等。

    进程的五种基本状态及其转换:

    • 创建状态:进程正在被创建,尚未转到就绪状态,创建进程需要申请一个空白的 PCB,并向 PCB 写一些控制和管理进程的信息,然后由系统分配资源,将进程转入就绪状态。
    • 就绪状态:进程已处于准备执行的状态,获得了除处理机以外的一切所需资源。
    • 执行状态:进程在处理机上运行。在单处理机环境下,每一时刻最多只有一个进程运行。
    • 阻塞状态:进程正在等待某一事件(服务请求)而暂停运行,如 等待某资源变为可用(不包括处理机)或等待输入输出 I/O 完成,即使处理机空闲,该进程也不能运行。
    • 结束状态:进程正从系统中消失,这可能是进程正常结束或其他原因中断退出运行,当进程需要结束运行时,系统首先必须置该进程为结束状态,然后再进一步处理资源释放和回收。

    注意:后备队列外存中,而就绪队列内存中。

    进程同步与互斥

    PV 操作是一种实现进程互斥与同步的有效方法。PV操作与信号量的处理相关,P 表示通过(荷兰语 passeren)的意思,V 表示释放(荷兰语 vrijgeven)的意思。

    具体来源可以查看PV操作的来源

    互斥与同步:

    • 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性排它性。但互斥无法限制访问者对资源的访问顺序,即 访问是无序的
    • 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

    在操作系统中,信号量S是一整数。
    S≥0 时,S 表示可供并发进程使用的资源实体数
    S<0 时,S 表示正在等待使用资源实体的进程数
    建立一个信号量必须说明此信号量所代表的意义并且赋初值。
    除赋初值外,信号量仅能通过PV操作来访问。

    • 信号量 S(semaphore) 代表“资源数”
    • P 操作的主要动作是:通过(荷兰语 passeren)(即 让进程使用资源
      • S 减 1;

        类比:“占用了一个资源”

      • 若相减结果仍大于或等于 0,则进程继续执行;

        类比:“若占用一个资源后,还有多余的资源或者刚好用完资源,那么就代表该进程有资源可以利用,进程也就可以继续执行

      • 若相减结果小于 0,则该进程被阻塞(挂起),之后放入等待该信号量的等待队列中,然后转入进程调度。

        类比:“若占用一个资源后,还欠别人资源,那么就代表该进程根本就没有资源可以用了,所以先欠着,挂个号,等待

    • V 操作的主要动作是:释放(荷兰语 vrijgeven)(即 让进程释放资源
      • S 加 1;

        类比:“资源占用完了,物归原主,释放资源”

      • 若相加结果大于 0,则进程继续执行;

        类比:“若释放资源后,资源数大于 0,就代表库存里的资源充裕,奉还资源后,还有资源可以给你利用,那就继续占用资源,继续执行

      • 若相加结果小于或等于 0,则从该信号的等待队列中释放一个等待进程(唤醒等待→就绪),然后再返回原进程继续执行 或转入进程调度。

        类比:“若一个进程结束,释放资源后,资源数还是欠别人的或者为 0,就代表库存里的资源很紧张资源刚一释放就被其他进程一抢而空,所以自己就不能用了,得先来后到把资源给下一个进程用,让下一个进程就绪
        如果执行不需要此资源,那么等自己执行完后(有的执行并不一定需要此资源)把处理机让给下一个进程用;
        如果执行需要此资源,那么转入进程调度,重新排队,等等再执行,把处理机让给下一个进程用,让下一个进程执行。”

    注意:PV 操作对于每一个进程来说,都只能进行一次,而且必须成对使用

    代码化如下:
    P 操作:

    P(S) {
        S--;
        if(S < 0) {
            保留调用进程CPU现场;
            将该进程的PCB插入S的等待队列;
            置该进程为“等待”状态;
            转入进程调度;
        }
    }

    V 操作:

    V(S) {
        S++;
        if(S <= 0) {
            移出S等待队列首元素;
            将该进程的PCB插入就绪队列;
            置该进程为“就绪”状态;
        }
    }

    进程通信

    根据交换信息量的多少和效率的高低,进程通信分为如下低级通信和高级通信。

    • 低级通信:只能传递状态和整数值(控制信息)。(如 同步互斥工具:PV 操作)

      由于进程的互斥和同步,需要在进程间交换一定的信息,故不少学者将它们也归为进程通信。

      • 特点:传送信息量小,效率低,每次通信传递的信息量固定,若传递较多信息则需要进行多次通信。
      • 编程复杂:用户直接实现通信的细节,容易出错。
    • 高级通信:提高信号通信的效率,传递大量数据,减轻程序编制的复杂度。
      提供三种方式:
      • 共享内存模式
      • 消息传递模式
      • 共享文件模式

    共享内存模式

    在通信进程之间存在一块可直接访问的共享空间,通过对这片共享空间进行写/读操作,实现进程之间的信息交换。

    在对共享空间进行写/读操作时,需要同步互斥工具(如 P操作、V操作),对共享空间的写/读进行控制。

    类比:
    进程 = 物品
    共享空间 = 钱
    用钱进行交换,而不用物物交换

    消息传递模式

    在消息传递模式中,进程间的数据交换是以格式化的消息(Message)为单位的。
    进程通过系统提供的发送消息接收消息两个原语进行数据交换。

    若通信进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的信息传递方法实现进程通信。

    可分为直接和间接两种通信方式:

    • 直接:将消息发送给接收进程,并将它挂在接收进程的信息缓冲队列中,接收进程从消息缓冲队列中取得消息。
    • 间接:将消息发送给某个中间实体(信箱),接受进程从中间实体中取得消息,又称为信箱通信方式。

      类比:
      甲给乙写信
      直接:甲直接把信交给乙
      间接:甲通过邮差把信交给乙

    共享文件模式

    共享文件:用于连接一个发送进程和一个接收进程,以实现它们之间通信的文件,就是共享文件,又名 pipe(管道)文件
    向管道提供输入的发送进程,以字节流形式将大量的数据送入管道;
    而接收管道输出的接收进程,则从管道中接收数据。

    为了协调双方的通信,管道机制必须提供互斥、同步和确定对方存在三方面的协调能力。

    线程

    对线程最基本的理解就是“轻量级进程”,它是一个基本的 CPU 执行单元,也是程序执行流的最小单元,由线程 ID、程序计数器、寄存器集合和堆栈组成。(即 CPU 调度的基本单元
    线程控制块(Thread Control Block, TCB):保存运行期间线程的数据,TCB线程存在的唯一标志

    • 线程属于进程,是进程的一个实体,是被系统独立和分配的基本单位。
    • 线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可以与同属一个进程的其他线程共享进程所拥有的全部资源。
    • 一个进程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。

    区别

    • 进程是资源分配和调度的一个独立单元;
      线程是 CPU 调度的基本单元。
    • 同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进程至少包括一个线程。
    • 进程的创建调用 fork 或者 vfork,而线程的创建调用 pthread_create;
      进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束。
    • 线程是轻量级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的。
    • 线程中执行时一半都要进行同步和互斥,因为它们共享同一进程的所有资源。
    • 线程有自己的私有属性 TCB、线程 id、寄存器、硬件上下文;
      进程也有自己的私有属性进程控制块 PCB,
      这些私有属性是不被共享的,用来表示一个进程或一个线程的标志。

    处理机调度

    • 高级调度:(作业调度外存 → 内存)根据某种算法,把外存上处于后备队列中那些作业调入内存
    • 中级调度:(内存调度内存 → 外存)将那些暂时不能运行的进程调至外存等待,把进程状态改为就绪驻外存状态挂机状态
    • 低级调度:(进程调度就绪 → 执行)按照某种算法从就绪队列(内存)中选取一个进程,将处理机分配给它。

    调度算法

    调度算法是根据系统的资源分配策略所规定的资源分配算法。
    有的调度算法适用于作业调度,有的适用于进程调度,有的两种都适用。

    • 周转时间=等待时间+执行时间

    先来先服务调度(FCFS)

    先来先服务调度(First Come First Service, FCFS):按照作业/进程进入系统的先后次序进行调度,先进入系统者先调度,即 启动等待时间最长的作业/进程。

    • 适用性:作业调度、进程调度。
    • 优点:
      • 算法简单
      • 作业/进程有利(短的要等好久)
      • 有利于CPU繁忙型作业/进程

        科普:CPU 繁忙意味着是长作业,不需要频繁的输入输出

    • 缺点:
      • 效率低
      • 对短作业/进程不利

        因为短作业执行时间很短,若令它等待较长时间,则带权周转时间会很高。

      • 不利于 I/O 繁忙型作业进程

        I/O 繁忙意味着不停地中断完成,是短作业

    短作业优先调度(SJF)

    短作业优先调度(Shortest Job First, SJF):该算法每次从后备队列/就绪队列中选择一个估计时间最短的作业/进程,将资源分配给它。

    • 适用性:作业调度、进程调度。
    • 优点:
      • 平均等待时间和平均周转时间最少
    • 缺点:
      • 对长作业/进程不利(可能导致长作业/进程长期不被调度,发生“饥饿”现象)
      • 不能保证紧迫性作业/进程会被及时处理
      • 由于作业/进程的长短只是根据客户说提供的估计执行时间而定的,而用户有可能会有意或无意地缩短气作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。

    优先级调度

    优先级调度:该算法每次从后备队列/就绪队列中选择优先级最高的一个作业/进程,将资源分配给它。

    • 适用性:作业调度、进程调度。

    根据新的更高优先级进程能否抢占正在执行的进程,可将该调度分为:

    • 非抢占式优先级调度算法:
      当有进程正在处理机上运行时,即使有更高优先级的进程进入就绪队列,也需等待当前进程运行完成,等待主动让出处理机后,才把处理机分配给高优先级的进程。
    • 抢占式优先权调度算法:
      当有进程正在处理机上运行时,只要又出现了另一个其优先权更高的进程,进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程。

    高响应比优先调度(HRRN)

    高响应比优先调度(Highest Response Ratio Next, HRRN):该算法是对 FCFS 调度算法和 SJF 调度算法的一种综合平衡,同时考虑每个作业的等待时间和估计的运行时间。

    在每次进行作业调度时,先计算后备作业队列中每个作业的响应比,从中选出响应比最高的作业投入运行。

    响应比=作业周转时间/作业执行时间=(等待时间+要求服务时间)/要求服务时间

    • 适用性:主要用于作业调度
    • 优点:
      • 等待时间相同的作业,要求服务的时间越短,其优先权越高,此时对短作业有利
      • 等待时间相同的作业,等待时间越长,其优先权越高,此时等同于先来先服务调度算法;
      • 对于长作业,优先权随等待时间的增加而提高,其等待时间足够长时,其优先权便可提升到很高,从而也可获得处理机,此时对长作业有利,克服了饥饿状态。
    • 缺点:
      • 要进行响应比计算,增加了系统开销。

    时间片轮转调度

    该算法将所有就绪进程按到达的先后次序排成一个队列,每次调度时,把处理机分配给队首进程,并令其执行一个时间片
    当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便停止该进程的执行,并将其放到就绪队列尾;
    然后,再把处理机分配给就绪队列中新的队首。

    • 适用性:主要用于分时系统中进程调度

    多级反馈队列调度

    该算法是时间片轮转调度算法优先级调度算法的综合和发展,通过动态调整进程优先级和时间片大小,可以兼顾多方面的系统目标。

    设置多个就绪队列,并赋予不同优先级,优先级越高,时间片越小,进程在进入待调度的队列等待时,首先进入优先级最高的 Q1 等待,一个时间片结束后,若进程没有运行完,则转入低一级的就绪队列队尾,仅当高优先级队列中无就绪进程才开始调度低一级的就绪队列中的进程(若此刻有进程进入了高优先级队列中,那么要先转去调用高优先级队列)。

    • 例子:
      假设系统中有 3 个反馈队列 Q1,Q2,Q3,时间片分别为 2,4,8。
      设有3个作业J1,J2,J3分别在时间 0,1,3 时刻到达。而它们所需要的 CPU 时间分别是 3,2,1 个时间片。
      1. 时刻 0:J1 到达。于是进入到队列 1,运行 1 个时间片,时间片还未到,此时 J2 到达。
      2. 时刻 1:J2 到达。由于同一队列采用先来先服务,于是 J2 等待。J1 在又运行了 1 个时间片后,已经完成了在 Q1 中的 2 个时间片的限制,于是 J1 置于 Q2 等待被调度。当前处理机分配给 J2。
      3. 时刻 2:J1 进入 Q2 等待调度,J2 获得 CPU 开始运行。
      4. 时刻 3:J3 到达,由于同一队列采用先来先服务,故 J3 在 Q1 等待调度,J1 也在 Q2 等待调度。
      5. 时刻 4:J2 处理完成,由于 J3,J1 都在等待调度,但是 J3 所在的队列比 J1 所在的队列的优先级要高,于是 J3 被调度,J1 继续在 Q2 等待。
      6. 时刻 5:J3 经过 1 个时间片,完成。
      7. 时刻 6:由于 Q1 已经空闲,于是开始调度 Q2 中的作业,则 J1 得到处理器开始运行。J1 再经过一个时间片,完成了任务。于是整个调度过程结束。

        从上面的例子看,在多级反馈队列中,后进的作业不一定慢完成。

    死锁

    死锁是指多个进程因竞争临界资源而造成的一种僵局(互相等待),若无外力作用,这些进程都无法向前推进。

    • 产生死锁的根本原因:系统能够提供的资源个数比要求该资源的进程数要少。
    • 产生死锁的基本原因
      • 资源竞争

        例子:
        A 有纸,B 有笔
        A:你不给我笔,我就不给你纸,我就写不了作业
        B:你不给我纸,我就不给你笔,我就写不了作业
        彼此僵持不下。。

      • 进程推进顺序非法

        例子:
        A 要前进 2 步,到桌子前拿东西,再后退 2 步;
        结果顺序非法:
        A 先后退,就永远到不了桌子前,触发不了,死锁。

    • 产生死锁的必要条件:(互斥、不剥夺、占有、环路)
      • 互斥条件:涉及的资源是非共享的,即 一次只有一个进程使用。如果有另一个进程申请该资源,那么申请进程必须等待,直到该资源被释放。

        互斥:有你没我,有我没你

      • 不剥夺条件(非抢占):进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即 只能由获得该资源的进程自己来释放。

        不剥夺:你不能强行抢我的

      • 占有并等待(部分分配):进程每次申请它所需要的一部分资源。在等待一新资源的同时,进程继续占用已分配到的资源。

        占有:这个资源我马上要用的,拿着等一会

      • 环路条件(循环等待):存在一种进程循环链,链中每一个进程已获得的资源同时被链中下一个资源所请求。

        环路:你不给我,我不给你

      注意:这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立;
      反之,只要上述条件之一不满足,就不会发生死锁。

    处理策略

    预防死锁

    预防死锁:通过设置一些限制条件,破坏死锁的一些必要条件,让死锁无法发生。

    避免死锁

    避免死锁:在动态分配资源的过程中,用一些算法(如 银行家算法)防止系统进入不安全状态,避免死锁的发生。

    银行家算法

    Dijkstra E W 于 1968 年提出银行家算法。之所以称为银行家算法,是因为该算法可用于银行系统。

    新进程进入系统时,它必须说明各类资源类型的实例的最大需求量,这一数量不能超过系统各类资源的总数。
    当进程申请一组资源时,该算法需要检查申请者对各类资源的最大需求量:

    • 如果系统现存的各类资源的数量可以满足当前它对各类资源的最大需求量时,就满足当前的申请;
    • 否则,进程必须等待,直到其他进程释放足够的资源为止。

    换言之,仅当申请者可以在一定时间内无条件地归还它所申请的全部资源时,才能把资源分配给它。

    死锁的检测及解除

    死锁的检测及解除:在死锁发生前不做任何操作,只是检测当前是否发生死锁,若发生死锁,则采取一些措施(如 资源剥夺法、撤销进程法、进程回退法)来解除死锁。

    主存管理

    实存管理:

    • 分区式管理:最简单直观的方式,在内存中连续分配一个区,将整个进程放入这个区。

      缺点是会产生外碎片,即 时间长了会在分区之间产生难以被利用的小空间。

      • 固定分区:把主存中可分配的用户区域预先划分成若干个连续的分区,每个连续区的大小可以相同,也可以不同。但是,一旦划分好分区之后,主存中分区的个数就固定了,且每个分区的大小也固定不变。这是一种静态分区法。
        在固定分区方式管理下,每个分区用来装入一个作业。由于主存中有多个分区,就可同时在每个分区中装入一个作业。所以,这种存储管理方式适用于多道程序系统。
      • 可变分区:内存管理的可变分区模式,又称变长分区模式、动态分区分配模式。
        这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统分区的大小和数目是可变的。

        与固定分区的区别就是:动态的划分分区。克服固定分区管理的“内碎片”问题。

    • 分页式管理:将内存分成固定大小的页,离散分配若干页将整个进程载入。

      页面可以不连续是其重要优点,不会产生外碎片,更有效地利用了内存,不过会产生一些内碎片,即 分配给进程的最后一个页往往不能正好用完,不过在页面大小不是很大的时候可以接受。

    • 分段式管理:将程序分为若干个段,如数据段和代码段,加以不同的保护。

      施加保护是分段式的优点,但其仍是像分区式管理一样的连续分配

    • 段页式管理:同样将程序分段,加以不同的保护,但是各段不再连续分配,而采用分页式离散分配

    注意:以上四种全是实存管理,即 进程要么全部载入内存中,要么就不能载入。

    虚存管理:

    • 请求式分页:将进程放入虚拟内存中,由于一个进程的页面不会同时全部被用到,只将需要用到的页面调入物理内存。即进程并没有整个在物理内存中。
      几个请求式分页的概念:
      • 固定分配:物理内存中分配给进程的内存块数一定。
      • 可变分配:物理内存先分配给进程一些内存块,如不够,可适当增加。
      • 局部置换:发生在分配的内存块已用完,又发生了缺页时,只能置换本来就是自己的内存块。
      • 全局置换:发生在分配的内存块已用完,又发生了缺页时,可以置换到操作系统保留的空闲页。这其实相当于增加了进程占有的内存块数。

        三种分配方式:固定分配局部置换、可变分配全局置换、可变分配局部置换。固定分配、全局置换不能组合。

    内存碎片

    内存碎片分为:内部碎片和外部碎片

    • 内部碎片:已经被分配出去(能明确指出属于哪个进程)却不能被利用的内存空间;

      内部碎片是处于(操作系统分配的用于装载某一进程的内存)区域内部或页面内部的存储块。
      占有这些区域或页面的进程并不使用这个存储块
      而在进程占有这块存储块时,系统无法利用它
      直到进程释放它,或进程结束时,系统才有可能利用这个存储块。

    • 外部碎片:还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。

      外部碎片是处于任何两个已分配区域或页面之间的空闲存储块。
      这些存储块的总和可以满足当前申请的长度要求,但是由于它们的地址不连续或其他原因,使得系统无法满足当前申请。

    分区存储管理

    分区存储管理中,程序的地址空间是一维线性的,因为是连续分配的,指令或操作数地址只要给出一个信息量即可决定。(连续分配

    分区式管理:最简单直观的方式,在内存中连续分配一个区,将整个进程放入这个区。

    缺点是会产生外碎片,即 时间长了会在分区之间产生难以被利用的小空间。

    • 固定分区:把主存中可分配的用户区域预先划分成若干个连续的分区,每个连续区的大小可以相同,也可以不同。但是,一旦划分好分区之后,主存中分区的个数就固定了,且每个分区的大小也固定不变。这是一种静态分区法。
      在固定分区方式管理下,每个分区用来装入一个作业。由于主存中有多个分区,就可同时在每个分区中装入一个作业。所以,这种存储管理方式适用于多道程序系统。
    • 可变分区:内存管理的可变分区模式,又称变长分区模式、动态分区分配模式。
      这种分配方式不会预先划分内存分区,而是在进程装入内存时,根据进程的大小动态地建立分区,并使分区的大小正好适合进程的需要。因此系统分区的大小和数目是可变的。

      与固定分区的区别就是:动态的划分分区。克服固定分区管理的“内碎片”问题。

    分区存储管理中常用的分配策略有:首次适应算法循环首次适应算法最佳适应算法最坏适应算法

    首次适应算法

    首次适应算法:地址从小到大排序,分配第一个符合条件的分区,即 第一个足够装入它的可利用的空闲区。

    • 优点:
      • 保留高地址部分的大空闲区,有利于后来的大型作业分配。
    • 缺点:
      • 低地址部分被不断划分,留下许多难以利用的小空闲区;
      • 每次分配时都要从低地址部分开始查找,增加查找时的系统开销。

    循环首次适应算法

    循环首次适应算法:在首次适应算法的基础上,从上次查找结束的位置开始查找,分配第一个足够装入它的可利用的空闲区。

    • 优点:
      • 使内存中的空闲分区分布更均匀,减少了查找时的系统开销。
    • 缺点:
      • 缺乏大的空闲区,可能导致不能装入大型作业。

    最佳适应算法

    最佳适应算法:按空间从小到大排序,分配第一个符合条件的分区,即 与它所需大小最接近的空闲区。

    • 优点:
      • 每次分配的空闲区都是最合适的
    • 缺点:
      • 在内存中留下许多难以利用的小空闲区

    最坏适应算法

    最坏适应算法:是按空间从大到小排序,分配第一个符合条件的分区,即 最不适合它的空闲区,即 最大的空闲区

    • 优点:
      • 产生碎片的几率最小,对中小型作业有利。
    • 缺点:
      • 缺乏大的空闲区,对大型作业不利。

    页式存储管理

    页式存储管理中,程序的地址空间是一维线性的,因为指令或操作数地址只要给出一个信息量即可决定。(离散分配

    理解:页式存储管理只用给出一个逻辑地址就行,因为页的大小是固定的,不需要刻意划分,当然不是逻辑地址÷页的大小=页号...余 偏移量,因为页式存储是离散分配的。
    根据下文的地址变换过程可知,我们只需要提供逻辑地址这一个地址,就可以找到这个页式存储物理地址,所以是地址空间一维的,只用一个逻辑地址。

    • 不存在外碎片,存在内碎片

      页之间一页紧跟着一页,没有外碎片;但是页内有可能分配不满,有内碎片。

    分页式管理:将内存分成固定大小的页,离散分配若干页将整个进程载入。于是一个连续的程序空间在主存中可能是不连续的。为了保证程序能正确地执行,必须在执行每条指令时将程序中的逻辑地址变换为实际的物理地址,即 进行动态重定位。
    在页式系统中,实现这种地址变换的机构称为页面映射表,简称页表

    页面可以不连续是其重要优点,不会产生外碎片,更有效地利用了内存,不过会产生一些内碎片,即 分配给进程的最后一个页往往不能正好用完,不过在页面大小不是很大的时候可以接受。

    其实如何利用页表来进行地址变换,这与计算机所采用的地址结构有关,而地址结构又与选择的页面尺寸有关。

    • 虚地址结构:(因为是逻辑上的虚拟地址,所以由人为规定结构,比较随意)

      页号 页内位移
      P W

      就如上表所示,虚地址是由页号页内位移组合而成。

    • 地址变换过程:(逻辑地址→物理地址
      在收到逻辑地址(Logic Address, LA)后,进行处理,得到物理地址(Physical Address, PA):
      1. 逻辑地址 LA 划分为页号 P页内位移 W
      2. 根据页号 P 查页表,得到块号 B
      3. 物理地址 PA = 块号 B * 页的大小 + 页内位移 W

    页面置换算法

    在地址映射过程中,若在页面中发现所要访问的页面不在内存中,则产生缺页中断
    当发生缺页中断时,如果操作系统内存中没有空闲页面,则操作系统必须在内存选择一个页面将其移出内存,以便为即将调入的页面让出空间。而用来选择淘汰哪一页的规则叫做页面置换算法

    抖动(颠簸):是指在页面置换过程中,刚刚调出的页面马上又要调入内存,刚刚调入的页面马上又要调出,发生频繁的页面调度行为。

    • 缺页中断率=成功访问次数/总访问次数
    • 最佳置换算法(OPTimal replacement, OPT):将以后永不使用的或者在最长时间内不会被访问的页面调出,但由于人们无法预知进程在内存下的若干页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。
    • 先进先出置换算法(First In First Out, FIFO):将最早进入内存的页面调出。

      该算法会产生Belady异常,即 发生缺页时,如果对一个进程未分配它所要求的全部页面,有时分配页数↑,缺页率反而↑的异常现象。(先进先出,结果进来了一个需要的页,也出去了一个需要的页)

    • 最近最久未使用置换算法(Least Recently Used, LRU):是将最近最长时间未访问的页面调出。该算法为每个页面设置一个访问字段,记录页面上次被访问以来所经历的时间,调出页面时选择时间最长的页面。
    • 最不经常使用置换算法(Least Frequently Used ,LFU):将最近应用次数最少的页淘汰。
    • 时钟置换算法(CLOCK):也称为最近未用算法(NRU),该算法是为每个页面设置一个使用位,需要替换页面时,循环检查各个页面,将使用位为 1 的页面重置为 0(使用时再置为1),直到遇到第一个使用位为 0 的页面,将其调出。
      如果在每个页面再增加一个修改位,则得到改进型的 CLOCK 置换算法,类似的,需要替换页面时,将使用位和修改位都为 0 的页面调出。

    段式存储管理

    段式存储管理的用户地址是二维的、按段划分的。(离散分配

    理解:段式存储管理必须给出(段号,偏移量),因为段的大小不固定,必须给出这个地址结构(逻辑地址),由此找到段表中程序员设置基址,由地址结构(逻辑地址)和基址这两个地址我们可以得到段式存储物理地址,所以是二维的,需要用到两个地址。

    • 存在外碎片,不存在内碎片

      段内紧密连接为一个整体,没有内碎片;段之间不一定紧密连接,存在外碎片。

    分段式管理:将程序分为若干个段,如数据段和代码段,加以不同的保护。

    施加保护是分段式的优点,虽然不同段可以离散分配,但其段内仍是连续分配。

    在这样的系统中作业的地址空间由若干逻辑分段组成,每个分段有自己的名字,对于一个分段而言,它是一个连续的地址区。

    • 由于标识某一程序地址时,要同时给出段名和段内地址,因此地址空间是二维的(实际上,为了实现方便,在第一次访问某段时,操作系统就用唯一的段号来代替该段的段名)。
    • 程序地址的一般形式由(s,w)组成,这里 s 是段号,w 是段内位移

      段号 段内位移
      s w

      注意:这里虽然和分页一样,但是进入段表后,要找到段表中程序员设置的基址,所以是二维的地址结构。

    分页和分段的异同

    相同点:

    • 分页和分段都采用离散分配(也就是不连续的分配地址,类似于链表)的方式
    • 都要通过地址映射机构来实现地址变换

    不同点:

    • 从功能上看:
      是信息的物理单位,分页是为实现离散分配方式,以消除内存的外零头,提高内存利用率,是为了满足系统管理的需要;
      是信息的逻辑单位,它含有一组意义相对完整的信息,是为了满足用户的需要。
    • 的大小是由系统确定且固定不变的;
      长度不固定,取决于用户编写的程序。
    • 分页的作业地址空间是一维的;
      分段的作业地址空间是二维的。

      理解:
      分页存储管理里面的地址结构是:页号+位移量,这个地址结构就是一个地址;
      根据页号在页表项中找到对应页项,这个页项代表了一个块号,但是这个块号并不是一个地址,因为所有块是事先已经划分好且长度相等的,这些块是操作系统自己知道的,所以操作系统就可以仅根据地址结构直接访问,即分页存储管理的地址空间是一维的。
      分段存储管理里面的地址结构是:段号+段内地址(位移量),这个地址结构就是一个地址;
      根据段号在段表项中找到对应段项,这个段项和页项的组成成分不一样,其中还包含了一个基址,就是段在内存中的起始地址,这个地址不是操作系统划分,而是程序员事先设置的,操作系统并不知道,所以操作系统要访问内存就必须要结合地址结构段表中的基址,所以分段的地址空间是二维的。

      总结:
      分页地址结构+块号,地址结构是地址,块号只是一个数字而已,所以是一维;(因为长度固定,所以只需要块号数字就行)
      分段地址结构+基址,两者都是地址,所以是二维的。(因为长度不固定,所以需要基址才能找到)

    段页式存储管理

    段页式存储管理的用户地址也是二维的、按段划分的。只是在段中再划分成若干大小相等的页

    理解:段页式存储管理也必须给出(段号,偏移量),虽然段的大小不固定,但是段内页号和页内偏移可以根据偏移量算出来,所以还是二维的。

    • 段页式管理:同样将程序分段,加以不同的保护,但是各段不再连续分配,而采用分页式离散分配

    • 地址结构就由段号、段内页号、页内位移三部分组成。

      注意:不要看三部分就是三维的了,其实用户使用的部分也是二维的。

    段号 段内页号 页内位移
    • 用户使用的仍是段号和段内相对地址
      由地址变换机构自动将段内相对地址的高几位解释为段内页号,将剩余的低位解释为页内位移

    • 用户地址空间的最小单位不是段而是,而主存按页的大小划分,按页装入。

      这样,一个段可以装入到若干个不连续的主存块内,段的大小不再受主存可用区的限制了。

    虚拟存储器

    虚拟存储器:是指具有请求调入功能和置换功能,并能从逻辑上对内存容量加以扩充的一种存储器系统。
    它使得应用程序认为它拥有连续的可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。

    • 局部性原理:是指CPU访问存储器时,无论是存取指令还是存取数据,所访问的存储单元都趋于聚集在一个较小的连续区域中。
      • 时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。

        程序循环、堆栈等是产生时间局部性的原因。

      • 空间局部性(Spatial Locality):在最近的将来将用到的信息很可能与正在使用的信息在空间地址上是临近的。
      • 顺序局部性(Order Locality):在典型程序中,除转移类指令外,大部分指令是顺序进行的。顺序执行和非顺序执行的比例大致是 5:1。此外,对大型数组访问也是顺序的。

        指令的顺序执行、数组的连续存放等是产生顺序局部性的原因。

    虚拟存储器基于局部性原理,在程序装入时,可以只将程序的一部分装入内存,就可以启动程序执行。
    在执行过程中,当所访问的信息不在内存中时,由操作系统将所需内容调入内存,使程序继续执行;

    解释:因为局部性原理,所以下一步需要访问的信息很有可能就在附近。

    同时,操作系统将内存中暂时不用的内容调出到外存。

    这样,系统就好像为用户提供了一个比实际内存大得多的存储器,称为虚拟存储器

    • 特征:
      • 离散性:是指内存分配时采用离散分配的方式。若采用连续分配方式,需要将作业装入到连续的内存区域,这样需要连续地一次性申请一部分内存空间,无法实现虚拟存储功能,只有采用离散分配方式,才能为它申请内存空间,以避免浪费内存空间。
      • 多次性:作业无需在运行时一次性全部装入内存,而是可以分成多次调入内存。
      • 对换性:作业运行时无需常驻内存,可以进行调入调出。
      • 虚拟性:从逻辑上扩充了内存的容量,使用户所感觉到的内存容量远大于实际容量。

    文件系统

    文件分配

    文件分配对应于文件的物理结构,是指如何为文件分配磁盘块(外存)。

    常用的磁盘空间分配方法有三种:

    • 连续分配:要求每个文件在磁盘上占有一组连续的块。
    • 链接分配:采取离散分配的方式,分为隐式链接分配和显式链接分配。

      类比:链表那样一个一个地顺序查找

      • 隐式链接分配:每个文件对应一个磁盘块的链表,磁盘块任意分布,除最后一个盘块外,每一个盘块都有指向下一个盘块的指针(类似于数据结构中的链表)。
      • 显式链接分配:把用于链接文件各物理块的指针提取出来,显式地存放在内存里的一张链接表中,该表整个磁盘仅设置一张,由于分配给文件的所有盘块号都放在该表中,故称该表为文件分配表(FAT)。

        这本质上仍然是链接分配,即 进程给出文件物理块起始地址等信息,然后根据内存FAT中地址的链接情况进行查找,得到所需物理块。在查找过程中仍然是一个一个地顺序查找

    • 索引分配:把每个文件的所有盘块号集中在一起构成索引块(表)。

      索引分配与显式链接分配不同,索引分配是随机查找,不需要借助前一个物理块来找到后一个,直接就可以查找到,直达

    磁盘调度算法

    调度算法 算法思想 优点 缺点
    先来先服务算法(FCFS) 按照进程请求访问磁盘的先后顺序进行调度。 简单,公平。 未对寻道进行优化,平均寻道时间较长,仅适用于磁盘请求较少的场合。
    最短寻道时间优先算法(SSTF) 选择与当前磁头所在磁道距离最近的请求作为下一次服务的对象。 较 FCFS 有较好的寻道性能以及较少的寻道时间。 会导致饥饿现象
    扫描(电梯调度)算法(SCAN) 在磁头当前移动方向上选择与当前磁头所在磁道距离最近的请求最为下一次服务的对象。 具有较好的寻道性能,而且防止了饥饿现象。 存在一个请求刚好被错过而需要等待很久的情形。
    循环扫描算法(CSCAN) 规定磁头单向移动,如自里向外移动,当磁头移动到最外的磁道时立即返回到最里磁道,如此循环进行扫描。 兼顾较好的寻道性能,防止饥饿现象,同时解决了一个请求等待时间过长的问题。 可能出现磁臂长时间停留在某处不懂的情况(磁臂黏着)。
    N-Step-SCAN 算法
    (对 SCAN算法的优化)
    将磁盘请求队列分成若干个长度为 N 的子队列,磁盘调度将按照 FCFS 依次处理这些子队列,而每处理一个队列时又是按照 SCAN 算法,对一个队列处理后再处理其他队列,将新请求队列放入新队列。 无磁臂黏着。
    FSCAN 算法
    (对 SCAN 算法的优化)
    将请求队列分成两个子队列,将新出现请求磁盘 IO 的进程放入另一个子队列。 无磁臂黏着。
    • 先来先服务算法(First Come First Service, FCFS):根据进程请求访问磁盘的先后顺序进行调度。
    • 最短寻找时间优先算法(Shortest Seek Time First, SSTF):选择处理的磁道是与当前磁头所在磁道距离最近的磁道,使每次的寻找时间最短。

      该算法会产生“饥饿”现象。

    • 扫描算法(SCAN):也叫电梯算法,在磁头当前移动方向上选择与当前磁头所在距离最近的请求作为下一次服务的对象。

      实际上是在 SSTF 算法的基础上规定了磁头运动的方向。

    • 循环扫描算法(Cyclic SCAN, C-SCAN):在SCAN算法的基础上规定磁头单向移动来提供服务,到达磁盘端点返回时,直接快速返回起始端。

      若磁头移动到最远端的请求后,即刻返回,而不是到达端点再返回,则将改进后的SCAN算法和C-SCAN算法称为LOOK算法和C-LOOK算法。

    I/O 管理

    I/O 控制方式

    • 程序 I/O 方式:计算机从外部设备读取数据到存储器,每次读取一个字的数据。对读入的每个字,CPU 需要对外设状态进行循环检查,直到确定该字已经在 I/O 控制器的数据寄存器中。

      该方式适用于早期的无中断计算机系统中。
      CPU 和 I/O 设备只能串行工作,导致CPU的利用率相当低。

    • 中断驱动 I/O 控制方式:允许 I/O 设备主动打断 CPU 的运行并请求服务,从而使 CPU 在对 I/O 控制器发送命令后可以做其他工作。

      该方法普遍用于现代的计算机系统中。
      由于数据中每个字在存储器与 I/O 控制器之间的传输都必须经过 CPU,仍然会消耗 CPU 较多的时间。

    • DMA I/O 控制方式:(CPU 与 I/O 并行)
      I/O 设备和内存之间开辟直接的数据交换通路,数据的基本单位是数据块,所传送的数据是从设备直接送入内存;
      或者相反,仅在传送数据块的开始和结束时需要 CPU 干预,数据传送是在 DMA 控制器的控制下完成的

      该方法适用于 I/O 设备为块设备时和主机进行数据交换。

      块设备是 I/O 设备中的一类,是将信息存储在固定大小的块中,每个块都有自己的地址,还可以在设备的任意位置读取一定长度的数据,如 硬盘、U 盘、SD 卡等。

      直接内存存取(Direct Memory Access, DMA)是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。
      否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU 对于其他的工作来说就无法使用。

    • I/O 通道控制方式:是 DMA 方式的发展,只在一组数据的传输开始和结束时需要 CPU 干预,可以实现 CPU、通道和 I/O 设备三者的并行操作。

      该方式适用于设备与主机进行数据交换是一组数据块的情况,使用该方法要求系统必须配置相应的通道及通道控制器。

    缓冲区

    引入缓冲区的目的是什么?

    • 缓和 CPU 与 I/O 设备间速度不匹配的矛盾;
    • 减少对 CPU 的中断频率,放宽对 CPU 中断响应时间的限制;
    • 解决基本数据单元大小(即 数据粒度)不匹配的问题;
    • 提高 CPU 和 I/O 设备之间的并行性。
  • 相关阅读:
    高性能javascript学习笔记系列(1) -js的加载和执行
    拖放 js
    js 内存小记
    原生方法系列 3(查缺补漏 不断更新)
    mongodb系列3 mongo mongoskin 连接以及连接数的问题进阶
    自定义浏览器alert ,抛弃掉死板的蓝框 自定义风格提示框。jquey ui bootstrap 实现自定义 alert confirm prompt ,by大崔
    CSS颜色代码大全
    WCF简单应用总结 by Jimmyzzc
    时间戳转换
    Ajax+MVC异常错误返回
  • 原文地址:https://www.cnblogs.com/blknemo/p/12274600.html
Copyright © 2020-2023  润新知