操作系统个人总结


参考: WINLSR操作系统博客

0、什么是操作系统?其功能和特征是什么?

  1. 定义:控制管理整个计算机软硬件资源,并且要进行工作和资源的调度,给用户和软件提供接口和环境。(调度就是指将资源具体分配给哪一个进程的动作,切换是指实际分配的行为动作,现有调度再有切换)
  2. 功能:
    1. 站在系统资源管理者角度(安全高效):CPU管理、存储器管理、文件管理、设备管理
    2. 站在用户和计算机硬件之间的接口看(为了方便用户使用):命令接口、程序接口、GUI
    3. 站在最接近硬件的角度看:实现对硬件机器的拓展
  3. 特征:(并发、共享)、虚拟、异步。

1、用户态、核心态?

  1. 是CPU运行的两种运行级别,代码会经过编译翻译成机器语言指令,一条高级语言代码翻译之后可能对应多条指令(CPU能识别、执行的最基本的命令)。
  2. 用户态:CPU只能执行非特权指令。核心态:CPU既可以执行特权指令也能执行非特权指令。
  3. CPU就是通过是否是特权指令将状态分为用户态和核心态。特权指令不允许用户程序使用,非特权指令就比如普通的运算指令是允许用户使用的。

1.1、哪些操作用导致用户态切换到核心态

  1. 中断会使用户态转为核心态,是CPU从用户态进入核心态的唯一实现途径。
  2. 中断的本质就意味着需要操作系统介入,开展管理工作。
  3. 中断分为内中断和外中断:
    1. 内中断:信号的来源:CPU内部与当前执行的指令有关(比如程序自身的错误)。
    2. 外中断:信号来源:CPU外部与当前执行的指令没有关系(比如IO操作完成之后发出的中断信号,或者用户强行终止一个进程)。
  4. 系统调用也会使用户态切换到核心态。(系统调用的作用:应用程序可以通过系统调用请求获得操作系统的服务)。此时是用户态进程主动要求切换到内核的一种方式。
    在这里插入图片描述

2、进程和线程

进程定义

  1. 进程:程序段+数据段+PCB(进程控制块,是进程存在的唯一标志)三部分(都放在内存中)组成进程实体(静态的)。进程(动态的)是进程实体的运行过程。(或者:进程是代码在计算机上的一次完整执行过程。)
  2. 线程:线程可以理解为轻量级的进程。线程的出现提高了并发度,并且减少并发带来的开销。

2.1、二者区别?

  1. 资源分配:进程是资源分配的基本单位;线程只能共享进程的资源。
  2. CPU调度:线程是调度的基本单位。同一进程中的线程切换,不会引起进程切换;不同进程中的线程切换,会引起进程切换。
  3. 系统开销:进程创建和销毁时,系统都要单独为它分配和回收资源,开销远大于线程的创建和销毁,进程的上下文切换需要保存更多的信息;线程(同一进程中)的上下文切换只需要保存线程的私有数据:栈、程序计数器(PC)等,系统开销更小。
  4. 通信方式:由于各个进程拥有各自独立的地址空间,因此进程之间的通信需要依靠进程间通信(IPC)机制;线程是共享进程资源,可以通过共享访问共享数据进行通信。

注:进程的上下文实际上包括用户级上下文和系统级上下文
用户级上下文是由用户程序段、数据段、运行时的堆和用户栈组成的用户空间信息。
系统上下文包括用户进程标识信息(PCB)、进程现场信息、进程控制信息和系统内核栈组成的内核空间信息。

2.2、多进程和多线程的区别?

  1. 多进程:
    1. 优点:内存隔离,单个进程的异常不会导致整个引用的崩溃,方便调试。
    2. 缺点:进程之间调用,通信和切换开销比线程大。
    3. 使用场合:目标自动能交互少,在资源和性能许可情况下,使用多进程完成隔离性较强的子功能。
  2. 多线程:
    1. 优点:提高系统的并行性,开销小。
    2. 缺点:没有内存隔离,单个线程崩溃会导致整个应用退出,发生异常不好定位。
    3. 使用场景:存在大量IO,网络等耗时操作,或者需要和用户交互的时候,使用多线程能提高系统并行性以及用户界面快速响应。

3、进程有哪些状态?这些状态是如何装换的?

状态及状态转换

  1. 进程的5中基本状态:创建、就绪、运行、阻塞、终止。
    在这里插入图片描述
    进程控制:本质就是要实现进程状态的转换。
    进程控制用原语实现,原语用关/开中断实现,原语是一种特殊的程序,其执行必须一气呵成,不可中断。

4、进程调度算法

  1. 先来先服务:按照作业/进程到达的先后顺序进行服务。
    1. 优点:公平、实现简单。
    2. 缺点:对长作业有利,对短作业不利。
    3. 不会产饥饿
  2. 短作业优先:最短的作业/进程优先得到服务。
    1. 优点:“最短的”平均等待时间、平均周转时间。
    2. 缺点:不公平的。对短作业有利,对长作业不利。
    3. 会产生饥饿
  3. 高响应比优先:只有当前运行的进程主动放弃CPU(正常/异常完成,或者主动阻塞),才需要进行调度,调度的时候计算所有就绪进程的响应比(响应比=(等待时间+要求服务时间)/要求服务时间),响应比最高的进程上处理机。
    1. 优点:是两种算法的折中,综合考虑等待时间和运行时间。
    2. 不会产生饥饿
  4. 时间片轮转调度算法:按照各个进程到达就绪队列,轮流让各个进程执行一个时间片。若进程没有在一个时间片内执行完,剥夺处理机,同时将进程重新放回到就绪队列的队列进行排队。
    1. 优点:公平,适用于分时操作系统。
    2. 缺点:高频的进程切换,因此有一定开销;不会区分任务的紧急程度。
    3. 不会产生饥饿
  5. 优先级调度算法:调度的时候选择优先级最高的作业/进程。
    1. 优点:用于优先级区分紧急程度,适用于实时操作系统。
    2. 会导致饥饿
  6. 多级反馈队列调度算法:会设置多级的接续队列,各级队列的优先级由高到低,时间片从小到大;每当有新的进程到达的时候先进入1级队列,按照FCFS原则排队等待被分配时间片,如果用完时间片进程还没有结束,那么进程进入下一级队列的队尾。如果是在最下级的队列,那么重新放回该队列队尾;只有第k级队列为空的时候,才会为K+1级对头的进程分配时间片。
    1. 优点:集成了上述算法(除高响应比)的优点于一身。
    2. 缺点:会导致饥饿。

5、什么是进程的同步、互斥?如何实现进程的同步和互斥?

  1. 同步是指有的进程之间需要相互配合完成工作,各个进程的工作推进需要遵循一定的先后顺序
  2. 进程互斥是指当一个进程访问某临界资源的时候,另外一个想要访问该临接资源的进程必须等待。临接资源的访问过程(进入区、临界区、退出区、剩余区)。
    1. 在进入区要检查是否可进入临界区,可进入就上锁。
    2. 临界区就是访问临接资源那段代码。
    3. 退出去负责解锁。
    4. 剩余区就是其余的代码部分。
  3. 用户进程可以通过使用操作系统提供的一对原语(P(wait)、V(signal))来对信号量进行操作,这样很方便的实现了进程同步、互斥。
    在这里插入图片描述
    让权等待原则:进不了临界区的进程要释放处理机,防止忙等。

6、死锁以及死锁产生的条件?

  1. 死锁:在并发的环境下,各个进程因为竞争资源而造成一种互相等待对方手中资源的,导致各个进程都阻塞,都无法向前推进的现象。
  2. 产生死锁的四个条件(只要其中有一个不成立,死锁就不会发生):
    1. 互斥条件:只有对必须互斥使用的资源争抢才会导致死锁(互斥资源竞争)。
    2. 不剥夺条件:进程所获得的的资源在未使用完之前不能有其他进程强行夺走,只能主动释放。(君子不夺人所爱)
    3. 请求和保持条件:进程已经保持了至少一个资源,但是又提出了新的资源请求,但此时该资源又被其他资源占有,此时请求进程被阻塞,但又对自己持有的资源保持不放。(贪得无厌)
    4. 循环等待:存在一种进程资源的循环等待链,链中每一个进程都已获得的资源同时被下一个进程所请求。(转圈圈)

7、处理死锁的策略有哪些?

在这里插入图片描述

7.1、预防死锁(破坏四个必要条件)

  1. 并不是所有应用场景都可以破坏互斥条件。比如:SPOOLing技术将一台独享打印机改造为可供多个用户共享的打印机。(破坏互斥条件)
  2. 当某进程请求新的资源得不到满足的时候,必须立即释放保持的所有资源以后需要的时候重新申请;或者需要的资源被其他进程占有的时候,可以由操作系统协助,将想要的资源强行剥夺(利用优先级)(破坏不可剥夺条件)
  3. 进程在运行前需要一次申请到他所需要的全部资源,在他的资源未满足前,不让他投入运行。(破坏请求和保持条件)
  4. 给资源编号,进程必须按照编号从小到大的顺序申请自己所需资源。(破坏循环等待条件)

7.2、避免死锁(银行家算法)

  1. 银行家算法的思想:在资源分配之前预先判断这次分配是否会导致系统进入不安全状态。当进程提出资源请求之后系统的资源能够满足该请求,如果分配之后系统是安全的,那么将进程分配资源,否则不予以分配,且该进程会被阻塞。

  2. 所需要的数据结构:

    1. Available[j]表示系统剩余的资源总数。
    2. Max[i,j]表示每个进程最大资源需求数。
    3. Allocation[i,j]表示每个进程已经分配到的资源数。
    4. Need[i,j]表示每个进程还需要的各类资源数(Need[i,j] = Max[i,j] - allocation[i,j])。
    5. R e q u e s t i [ j ] Request_i[j] Requesti[j]表示某个进程的请求资源数。
  3. 算法流程:(0<=j<=m)

    1. 如果 R e q u e s t i [ j ] Request_i[j] Requesti[j]<=Need[i,j](本次请求的资源数不大于该进程最大需要的资源数),转向2;否则认为出错(正常的请求资源数应该是小于等于最大需求资源数)
    2. 如果 R e q u e s t i [ j ] Request_i[j] Requesti[j]<=Available[j](本次请求资源数不大于系统剩余的资源数),转向3;否则该进程必须等待(因为此时系统的资源剩余满足不了)。
    3. 系统试探着把资源分配给进程Pi,并修改响应数据。
      Available[j] = Available[j] – Request[j] Allocation[i, j] = Allocation[i, j] + Request[j] Need[i, j] = Need[i, j] –Request[j]
    4. 尝试分配之后,执行安全性算法,检查此次分配后系统是否处于安全状态,如果安全,才正式分配;否则恢复相应数据,让进程阻塞等待。
  4. 安全性算法:

    1. 检查当前剩余可用资源是否能满足某个进程的最大需求,如果可以,就把该进程加入安全序列。
    2. 同时回收该进程持有的所有资源
    3. 不断重复上述过程,看最终是否能让所有进程都加入安全序列。
  5. 系统处于不安全状态未必细说,但死锁一定处于不安全状态。系统安全状态一定不会死锁。

  6. 视频讲解例题讲解
    其实银行家算法最主要的就是四个矩阵:

  1. Available:系统可利用的各种资源的数量
  2. Max:每个进程对每种资源的最大需求数
  3. Allocation:每个进程已经分配的各类资源数
  4. Need:每个进程还需要各类资源的数量。
    Need = Max - Allocation
    在这里插入图片描述
    画表:
    (2):
    在这里插入图片描述
    在这里插入图片描述
    (3):
    新的请求要看是否≤Need以及是否≤Available,必须要都满足才可以。
    在这里插入图片描述
    注:只要能找出一个安全序列,系统处于安全状态,当然,这个序列不止一个。但如果分配资源后,系统找不出任何的安全序列,系统就不是安全状态。

7.3、检测和解除

  1. 允许死锁发生。
  2. 如果系统中既不采用预防死锁也不采用避免死锁的措施,系统就很有可能发生死锁。这种情况下,系统应当提供两种算法应对极有可能发生的死锁。
    1. 死锁检测算法:用于检测系统状态,确定系统中是否已经发生了死锁。
      需要利用资源分配图。
      在这里插入图片描述

      1. 死锁检测算法:依次消除与不阻塞进程相连的边,直到无边可消;不可简化的话,那么此时发生了系统死锁。
    2. 死锁解除算法:当认定系统中已经发生死锁,利用该算法可将系统从死锁中解脱出来。

      1. 资源剥夺法:挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。此时应该放置被挂起的进程长时间得不到资源而产生饥饿。
      2. 撤销进程法:强制撤销部分甚至全部死锁进程,并剥夺这些进程的资源。撤销的原则可以按照进程优先级和撤销进程的代价高低进行。
      3. 进程回退法:让一个或者多个死锁进程回退到足以避免死锁的地步。这需要系统记录进程的历史信息,设置还原点。

5、进程间通信(IPC)的方式有哪些?

  1. IPC:Inter-Process Communication
  2. 为什么要进程间通信?保护进程地址空间不会随便被不相干其他的进程访问,确保进程正常运行。但是进程和进程又需要协作完成任务,此时就需要通知、数据传递等。那么在保持进程的独立的同时去确保进程有效沟通
  3. 进程通信按照发送路径可以分为:进程进行通信和同步的机制。按照发送是否阻塞可以分为阻塞通信非阻塞通信
  4. 通信链路缓冲:
    1. 为什么要缓存消息?目的:提高效率,避免接发双方不匹配,同时缓存临时不能处理的数据。
    2. 按照缓存的容量可以分为:0容量、有限容量(队满发送方必须等待)、无限容量(发送方只管发就可以,不需要等待)。

5.1、管道

  1. 管道是很早期的进程间通信机制。是间接通信。
  2. 管道的是指是一个内核缓冲区进程先进先出的方式从缓冲区存取数据,管道一段的进程按照顺序将数据写入缓冲区,另一端的进程则按照顺序读出数据。
  3. 缓冲区可以看成是一个循环队列读写的位置都是自动增长的,不能随意改变,一个数据只能被读一次,读出来之后在缓冲区就不复存在了
  4. 当缓冲区读空或者写满的时候,有一定的规则控制相应的读进程或者写进程进入等待队列,当空的缓冲区有新数据写入或者满缓冲区有数据读出的时候,就唤醒等待队列中的进程继续读写。
    在这里插入图片描述

5.1.1、管道特点

  1. 管道是半双工的,数据只能像一个方向流动;需要双方通信的时候,需要建立两个管道。
  2. 只能用于父子进程或者兄弟进程之间
  3. 单独构成一种独立文件系统:管道对于管道两端的进程而言,就是一个文件,但却不是一个普通文件,管道不属于某种文件系统,是自立门户,单独构成一种文件系统,并且只存在于内存中
  4. 数据的读写:一个进程向管道中写的内容会被管道另一端的进程读出。写入内容每次都添加在管道缓冲区的末尾,并且每次是从缓冲区的头部读出数据。

5.2、命名管道

  1. 克服了管道没有名字限制,功能上除了管道具有的之外,同时还允许无亲缘关系进程之间的通信
  2. 命名管道提供一个路径名与之关联以文件形式存储文件系统中,只要进程可以访问该路径,就可以通过该命名管道相互通信
  3. 通过有名管道不相关的进程也可以交换数据
  4. 遵循先进先出的原则,对于匿名管道以及有名管道的读总是从开始出返回数据,写则是把数据添加到末尾,与管道一样。

5.3、信号

  1. 中断是有外设发给CPU的,能让CPU做某些事,会产生一个硬件中断。
  2. 信号是进程间的软件中断通知和处理机制。信号用于通知接收进程有某种事件发生,接收到该信号的进程会相应的采取一些行动
  3. 比如:SIGKILL,SIGSTOP,SIGCONT等。
  4. 信号的接收处理:
    1. 捕获:执行进程执行的信号处理函数被调用。每个进程有不同处理方法。
    2. 忽略:由操作系统的缺省处理内存处理进程信号。比如:进程终止、挂起等。
    3. 屏蔽:禁止进程接收和处理信号。
  5. 缺点:出送的信息量小,只有一个信号类型。
    在这里插入图片描述

5.4、消息队列

  1. 消息队列是间接通信。
  2. 是为了克服管道的缺点:1、进程没有父子关系,管道无法工作;2、管道的数据是一种字节流,没有结构化展示。
  3. 本质就是位于内核空间的链表,链表的每一节点都是一条消息每一条消息都有自己的消息类型,消息类型由发送方和接收方约定的。
  4. 与管道区别:从消息队列读取数据的时候不一定按照先进先出的顺序进行读取,也可以按照消息类型进行读取。
  5. 消息队列的生命周期是伴随内核的,因为消息队列存放在内核中,只有内核重启(操作系统重启)或者显示删除一个消息队列的时候,该消息队列才会被真正的删除
    在这里插入图片描述

5.5、共享内存

  1. 共享内存是直接通信
  2. 不同程序拥有各自的独立的逻辑地址空间,不能相互访问的
  3. 共享内存通过将一块物理内存映射到不同进程的逻辑地址空间,使得他们可以访问同一块物理内存,从而实现共享内存
  4. 访问共享共存区域和访问进程独有的内存区域一样快,读取和写入的过程中不用像管道和消息队列那样在用户态和内核态之间进行拷贝。所以共享内存是最快的进程间的通信方式
  5. 由于多个进程共享同一块内存区域,为保证正确通信,还需要借助同步机制信号量来进行同步。

5.6、信号量

  1. 信号量就是一个计数器用于多进程对于共享数据的访问,信号量的意图在于进程之间的同步
  2. 每当有进程申请使用信号量,通过一个P操作对信号量进行-1操作,当计数器减到0的时候就说明没有资源了,其他进程继续访问就会被阻塞当前进程执行完这段工作就会释放临界资源,就会执行V操作来对信号量进行+1操作,被阻塞的进程就会被唤醒

5.7、套接字

  1. 是一般的进程之间的通信机制,可以用于运行在不同主机上的进程之间的通信。通过IP地址和端口号确定一台主机上一个进程,通常用于网络编程。

6、内部碎片和外部碎片分别是什么?

内部碎片是指分配给某进程的内存区域中,有些没有用上的。(分了,但是没用完)
外部碎片是指内存中某些空闲分区由于太小而难以利用。(内存本身空闲分区太小就用不了)

7、常见内存管理方式

  1. 为什么需要对内存进行分配? 因为操作系统站在资源管理者的角度,需要对内存资源进行管理。
  2. 内存管理机制分为连续分配管理方式和非连续分配管理方式
    在这里插入图片描述
    各个连续分配方式的缺点:
    1. 单已连续分配只能适用于单用户。
    2. 固定分区分配缺乏灵活性,并且会产生大量的内部碎片,内存利用率极低;
    3. 动态分区分配会产生很多外部碎片,虽然可以利用及凑技术处理,但是时间代价太高。

7.1、基本分页存储管理

  1. 基本思想:把内存划分为一个个相等的小分区,再按照分区的大小把进程拆分成一个个小部分。

7.1.1、一些基本概念

在这里插入图片描述

7.1.2、地址转换

所谓的地址转换就是从如何从逻辑地址转换为物理地址。
内存地址是由低到高的。

步骤:

  1. 算出逻辑地址对应的页号
  2. 知道该页号对应页面在内存中的起始地址
  3. 算出逻辑地址在页面内的偏移量
  4. 物理地址=页面起始地址+页内偏移量

其逻辑地址的结构:
以32位操作系统举例,如果此时页面大小为4KB = 4 * 1024 = 2 12 2^{12} 212B,那么说明前32-12=20位表示页号,后12位表示页面偏移量
在这里插入图片描述
虽然此时已经知道了页号了页内偏移量,满足了步骤1、3,但是无法知道该页号对应的页面在内存中的起始地址,此时需要借助页表。
在这里插入图片描述

页表:就是为了知道进程每个页面在内存中存放的位置,也就是该页面在内存中起始地址。
在这里插入图片描述
在这里插入图片描述

整个过程如图所示:
在这里插入图片描述

7.2、基本分段存储管理

基本思想:进程的地址空间是按照程序自身的逻辑关系进行划分,划分为若干个段,每个段都有一个段名,每段从0开始编址。
内存分配规则:以段位单位进行分配每个段在内存中占据连续的空间,但是各个段之间是可以不相邻的。

7.2.1、地址转换

逻辑地址结构=段号(高位)+段内地址/段内偏移量(低位),段号决定每个进程最多可以分几个段,段内地址地址位数决定了每个段的最大长度是多少。
同样仅仅依靠段号和段内偏移地址是无法完成地址转换的。

段表:由于程序是分为多个段,且各个段是离散的转入内存,需要从物理内存中找到各个逻辑段的存放位置,就需要为每个进程建立一张映射表。
段表 = 段号+段长(段的长度)+基址(该段在内存中的起始位置)。各个段表项的长度是相同的。
在这里插入图片描述

在这里插入图片描述

步骤:

  1. 根据逻辑地址得到段号、段内地址。(比如某段程序经过编译之后,形成等价的机器指令,取出段号为2,段内地址为1024的内存单元的内容)
  2. 根据段表寄存器中的段表长长度(从1开始)进行判断与段号(从0开始)的大小关系,一旦段号≥段长,产生越界中断;否则继续进行。
  3. 根据段号和段表始址查询段表,找到段号对应的段表项,段表项=段表起始地址(在段表寄存器中)+段号*段表项长度。
  4. 得到段表项的存放地址之后,去段表中进行检查段内偏移量,如果段内偏移量≥段长,那么产生越界中段;否则继续执行。
  5. 根据段表项的基址+段内偏移就得到了实际存储在内存中的物理地址。
    在这里插入图片描述
    在这里插入图片描述

注:页表和段表都是存放于内存中,且都是占用连续空间。

7.3、分段和分页的区别

  1. 页是信息的物理单位分页的主要目的是实现离散分配,提高内存利用率。分页仅仅是系统管理上的需要,是系统行为,对用户不可见的。
  2. 段是信息的逻辑单位分段的主要目的是更好的满足用户需求。分段对用户是可见的,用户编程的时候需要显示的给出段名。
  3. 页的大小是由系统决定的。段的长度是不固定的,决定于用户编写的程序。
  4. 分页的用户进程地址空间是一维的,分段的用户进程地址空间是二维的。(多了一个段表寄存器)
  5. 分段比分页更容易实现信息的共享和保护。分段管理中,程序和数据本就按逻辑段存储在内存段中,容易实现对程序段、数据段的共享控制以及保护控制;而分页管理中,逻辑上的代码段或数据段是被分散的存储在各个离散的内存页帧当中,很难实现对逻辑程序段或逻辑数据段的共享与保护。

7.4、段页式存储管理

  1. 为什么要有段页式管理?
    1. 分页管理:不会产生外部碎片,内部空间利用率高,但是不方便按照逻辑模块实现信息的共享和保护。
    2. 分段管理:很方便按照逻辑模块实现信息的共享和保护;但如果段长过大,为其分配很大连续空间是很不方便的,其次分段管理会产生外部碎片(可以通过紧凑技术解决)。
  2. 段页式存储管理结合了二者的优点。将用户进程按照逻辑模块进行分段,之后再将各个段进行分页,再将内存空间划分为大小相同的内存块。并且装入内存块中

7.4.1、地址转换

逻辑地址结构 = 段号(决定了每个进程最多可以分为几个段)+页号(每个段最多有多少页)+页内偏移量(决定了页面的大小,内存块大小)组成。
在这里插入图片描述
需要段表和页表完成地址转换工作。
在这里插入图片描述
举例:
这里访问0号段,通过段表项的页表存放块号知道在是内存为一号块的地址,那么从1号块读出0号段对应的页表,由于每个内存块大小为4KB,而0号段是7KB,那么就被分为两个页面。相应的,两个页面对应依次对应页表中的页表项,每个页表项记录每个页面的内存块号地址。

段表项 = 段号(隐含的) + 页表长度 + 页表存放块号(页表起始地址)。

页表项 = 页号(隐含的) + 内存块号。
一个进程对应一个段表,每个段对应一个页表,一个进程可能对应多个页表。每个段对应一个段表项。每个页面对应一个页表项 。

步骤:

  1. 根据逻辑地址得到段号、页号、页内偏移量。
  2. 由段表寄存器中的段表长度判断段号是否越界(同分段)。
  3. 没有越界,那么就查询段表得到段表项(同分段),得到段号对应的段表项在内存中的位置。
  4. 由于各个段长度是不一样的,各个段进行分页也是不等的,此时检查页号是否越界了,如果页号≥页表长度,发生了越界中断。
  5. 没有产生越界中断,就继续执行,通过页表存放块号得知页表存放的位置,读出页表,再根据页号找到页表项,通过页表项中的内存块号得知该页面在内存中的位置。
  6. 最后根据内存块号和页内偏移量得到最终的物理地址。
    在这里插入图片描述
    在这里插入图片描述

8、虚拟内存

传统存储管理方式的特征、缺点(连续分配、非连续分配)
特征:1、一致性:作业必须一次性全部转入内存才能开始运行(缺点:1、大作业无法运行;2、多道程序并发度下降);2、驻留性:一旦作业被装入内存,就会一直驻留内存(缺点:浪费内存资源)

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

虚拟存储的定义:基于局部性原理,在程序装入的时候,可以将程序中很快会用到的部分装入内存暂时用不到的部分留在外存,就可以让程序开始执行。在程序执行的过程中,当所访问的信息不在内存的时候,由操作系统负责将所需要的信息从外存调入内存,然后继续执行程序。如果内存空间不够,由操作系统负责将内存中暂时用不到的信息换出到外存。那么,在操作系统的管理下,给用户提供了一个看起来似乎有一个比实际内存大得多的内存。

虚拟存储的特征:多次性(相比一次性)、对换性(对比驻留性)、虚拟性(从逻辑上看是扩充了内存容量)

虚拟内存的实现:

  1. 请求分页存储管理
  2. 请求分段存储管理
  3. 请求段页式存储管理

与非连续分配存储管理的区别:

  • 当访问的信息不在内存的时候,由操作系统负责将所需要的信息从外存调入内存。(请求调页功能)
  • 当内存空间不够的时候,将内存中暂时用不到的信息换出到外存(页面置换功能)

32位操作系统的虚拟内存可以多大?32表示给内存编号只能到 2 32 2^{32} 232,那么最大内存就是 2 32 2^{32} 232字节,也就是4G,那么内存的最大容量也是4G,但是虚拟内存的实际容量=min(4G,内存大小+外存大小)

9、页面置换算法

  1. 最佳淘汰算法:优先淘汰将来最长时间内不再被访问的页面,会保证最低的缺页率,但是无法实现的,可以作为衡量其他算法优劣标准。
  2. 先进先出淘汰算法:优先淘汰最先进入的页面。将那些经常被访问的页面也被换出,缺页率升高。随着队列大小增加,可能出现Belady现象(当为进程分配的物理块数增加的时候,缺页次数不降反增)。
  3. 最久未使用淘汰算法(LRU):优先淘汰最近最久未使用的页面。
  4. 时钟淘汰算法:为每个页面设置一个访问位,再将内存中的页面通过指针连接成一个循环队列。当某个页面被访问的时候,其访问位置置为1。当要淘汰某一个页面的时候,只需要检查页的访问位。如果是0就淘汰,是1暂时不淘汰,将访问位改为0,继续检查下一个页面。如果第一轮查找中所有页面都是1,那么这些页面的访问位会被依次置为0,在第二轮扫描中一定可以找到访问位为0的页面,将其淘汰。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值