操作系统题目

操作系统题目

img

操作系统的作用和功能

  • 在计算机系统上配置的操作系统,其主要目的是:方便性、有效性、可扩充性和开放性;

    1. 方便性

      未配置操作系统的计算机系统难以直接使用,因为此时对计算机系统的操作需要使用机器语言来完成;通过操作系统提供的各种命令来操作计算机极大方便了用户,使的计算机系统易学易用;

    2. 有效性

      操作系统的有效性有两层含义:

      第一层含义是提高系统资源的利用率。在未配置操作系统的计算机系统中,处理机和IO设备经常处于空闲状态,系统资源利用率低下;

      第二层含义是提高系统的吞吐量。操作系统通过合理组织计算机的工作流程,加速程序的运行,缩短程序的运行周期以实现系统吞吐量的提高;

      可以说,提高系统资源的利用率是推动OS发展的最重要动力;

      方便性和有效性是设计OS时最重要的两个目标。由于以前计算机系统比较昂贵,有效性显得更为重要;现在随着硬件的高速发展,方便性越来越突出,比如微机操作系统中的图形用户界面以及为程序员提供的大量系统调用接口方便了计算机系统的使用者和开发者;

    3. 可扩充性

      为了适应计算机硬件、计算机体系结构以及应用程序的发展,操作系统需要有很好的可扩充性。而可扩充性主要受操作系统结构的影响,因此提高操作系统的可扩充性在一定程度上促进了OS结构的不断发展:从早期的无结构到发展成模块化结构进而发展到层次化结构,现在OS广泛采用微内核结构。

      微内核结构可以方便地添加、修改相应的功能和模块,具有良好的可扩充性。

    4. 开放性

      计算机应用的日益普及,使得计算机软、硬件的兼容变得重要起来;随着操作系统的应用环境由单机环境转向网络环境,其开放性变得尤为重要;

      所谓的开放性是指,系统遵守世界标准规范,特别是开放系统互联OSI国际标准,遵守国际标准开发软、硬件都可以彼此兼用,方便实现互联;

      开放性是20世纪90年代后计算机技术的一个核心问题,也是衡量一个新系统能否被广泛应用的关键;

    操作系统的作用

    操作系统在计算机系统中所起的作用可以从用户、资源管理以及资源抽象等不同角度考虑;

    1. OS是用户和计算机硬件系统之间的结构

      OS位于用户和计算机硬件系统之间,使用户可以快速、准确、可靠地操作计算机硬件以及运行自己的程序。用户有三种方式使用计算机:命令(直接使用操作系统提供的命令来使用计算机硬件)、系统调用(编写一段C程序,通过操作系统提供的系统调用来使用计算机)、图标-窗口(如在Windows系统中通过双击图标等方式使用计算机);

    2. OS是计算机系统资源的管理者

      计算机系统中存在多种硬件和软件资源,总体来说这些资源可以分为:处理机、存储器、IO设备以及文件(包括程序和数据),OS的作用就是管理这些系统资源;

      1. 处理机管理:分配和管理;

      2. 存储器管理:内存分配和回收;

      3. IO设备管理:分配与操作;

      4. 文件管理:存取、共享、保护

        由于多用户同时使用一台计算机时,会发生系统中共享资源需求的冲突。操作系统需要对使用资源的请求作出授权以协调多用户的使用;

    3. OS实现了对计算机资源的抽象

      OS是铺设在计算机硬件上的多层软件的集合;它们不但增强了系统的功能,还隐藏了对硬件操作的细节,实现了对计算机硬件操作的多个层次的抽象模型;随着抽象层次的提高,抽象接口所提供的功能就越强,用户使用起来就越方便;

      这里需要注意的是,操作系统将具体的硬件抽象为一组数据结构来实现对硬件的隐藏,并向上提供一组针对这一数据结构的方法来隐藏对硬件的操作。

操作系统基本特征
  • 并发

    • 并发是指宏观上在一段时间内能同时运行多个程序,而并行则指同一时刻能运行多个指令。
    • 并行需要硬件支持,如多流水线、多核处理器或者分布式计算系统。
    • 操作系统通过引入进程和线程,使得程序能够并发运行。
  • 共享

    • 共享是指系统中的资源可以被多个并发进程共同使用。
    • 有两种共享方式:互斥共享和同时共享。
    • 互斥共享的资源称为临界资源,例如打印机等,在同一时刻只允许一个进程访问,需要用同步机制来实现互斥访问。
  • 异步

    • 异步指进程不是一次性执行完毕。
  • 虚拟

    • 虚拟技术把一个物理实体转换为多个逻辑实体。
    • 主要有两种虚拟技术:时分复用技术和空分复用技术。
    • 多个进程能在同一个处理器上并发执行使用了时分复用技术,让每个进程轮流占用处理器,每次只执行一小个时间片并快速切换。
    • 虚拟内存使用了空分复用技术,它将物理内存抽象为地址空间,每个进程都有各自的地址空间。地址空间的页被映射到物理内存,地址空间的页并不需要全部在物理内存中,当使用到一个没有在物理内存的页时,执行页面置换算法,将该页置换到内存中。
    基本功能
    • 进程管理
      • 进程控制、进程同步、进程通信、死锁处理、处理机调度等。
    • 内存管理
      • 内存分配、地址映射、内存保护与共享、虚拟内存等。
    • 文件管理
      • 文件存储空间的管理、目录管理、文件读写管理和保护等。
    • 设备管理
      • 完成用户的 I/O 请求,方便用户使用各种设备,并提高设备的利用率。
      • 主要包括缓冲管理、设备分配、设备处理、虛拟设备等。
    系统调用?用户态VS内核态
    • 根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别:

      • 用户态:用户态运行的进程或可以直接读取用户程序的数据。

      • 内核态:系统态运行的进程或程序几乎可以访问计算机的任何资源,不受限制。

    • 如果一个进程在用户态需要使用内核态的功能,就进行系统调用从而陷入内核,由操作系统代为完成

  • 凡是与资源有关的操作(存储分配、I/O、管理文件等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成

    • 用户程序执行陷入指令(trap指令)发起系统请求,将CPU使用权主动交给操作系统内核,即CPU状态会从用户态进入内核态
  • 操作系统处理完系统调用的请求后,又会把CPU使用权还给用户程序,即CPU状态会从内核态回到用户态

    • 目的:用户程序不能直接执行对系统影响非常大的操作,保证系统的稳定性和安全性,防止用户程序随意更改或访问重要的系统资源,影响其他进程的运行
  • 注:从用户态到内核态,不仅状态需要切换,而且所用的堆栈也可能需要从用户堆栈切换为系统堆栈(系统堆栈也属于该进程)

    系统调用可以分为如下几类:

    • 设备管理:完成设备的请求和释放,以及设备启动等功能
      • 文件管理:完成文件的读、写、创建及删除等功能
    • 进程控制:完成进程的撞见、撤销、阻塞及唤醒等功能
      • 进程通信:完成进程之间的消息传递或信号传递等功能
    • 内存管理:完成内存的分配、回收以及获取作业占用内存大小及初始地址等功能
  • 中断是指CPU对系统发生的某个事件做出的一种反应,CPU暂停正在执行的程序,保存现场后自动去执行相应的处理程序,处理完该事件后再返回中断处继续执行原来的程序。

    中断分类

    image.png

    中断(也称外中断)

      • 由 CPU 执行指令以外的事件引起,即与处理器运行的程序无关
      • I/O 中断:表示设备输入/输出处理已经完成,希望处理器能够发送下一个输入/输出请求,同时让完成输入/输出的程序继续运行
      • 时钟中断:表示一个固定的时间片已到,让处理器处理定时运行的任务

    异常(也称内中断)

    ​ 由 CPU 执行指令的内部事件引起,如非法操作码、地址越界、算术溢出等

    硬中断/软中断

    • Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部

      上半部用来快速处理中断,它在中断禁止模式下运行,主要处理跟硬件紧密相关的或时间敏感的工作

      • 网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它

        下半部用来延迟处理上半部未完成的工作,通常以内核线程的方式运行

      • 网卡接收到数据包后,会通过硬件中断的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它

    • 上半部:把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个软中断信号,通知下半部做进一步的处理

    • 上半部直接处理硬件请求,也就是我们常说的硬中断,特点是快速执行

    • 下半部:下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序

    • 下半部则是由内核触发,也就是我们常说的软中断,特点是延迟执行

    • 硬中断:

      • 硬中断是由硬件产生的,比如,像磁盘,网卡,键盘,时钟等。每个设备或设备集都有它自己的IRQ(中断请求)
        • 当中断产生的时候,CPU会中断当前正在运行的任务,来处理中断。在有多核心的系统上,一个中断通常只能中断一颗CPU
        • 硬中断可以直接中断CPU。它会引起内核中相关的代码被触发。对于那些需要花费一些时间去处理的进程
        • 对于时钟中断,内核调度代码会将当前正在运行的进程挂起,从而让其他的进程来运行。它的存在是为了让调度代码(或称为调度器)可以调度多任务。
      • 软中断:
      • 软中断是利用硬件中断的概念,用软件方式进行模拟,实现宏观上的异步执行效果。很多情况下,软中断和"信号"有些类似,同时,软中断又是和硬中断相对应的,“硬中断是外部设备对CPU的中断”,“软中断通常是硬中断服务程序对内核的中断”,“信号则是由内核(或其他进程)对某个进程的中断”
        • 软中断是实现系统API函数调用的手段
        • 通常,软中断是一些对I/O的请求。这些请求会调用内核中可以调度I/O发生的程序。
        • 软中断仅与内核相联系。而内核主要负责对需要运行的任何其他的进程进行调度
        • 软中断并不会直接中断CPU。也只有当前正在运行的代码(或进程)才会产生软中断。这种中断是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求。有一个特殊的软中断是Yield调用,它的作用是请求内核调度器去查看是否有一些其他的进程可以运行。
    中断处理的流程

    image.png

    • 13步在CPU进入中断周期后,由硬件自动完成,49步由中断服务程序完成
    • 恢复现场指在中断返回前,必须将寄存器的内容恢复到中断处理前的状态,由中断服务程序完成
    1. 关中断
      • CPU关闭响应更高级中断源的中断请求,否则现场保存不完整
    1. 保存断点
      • 将原来程序的程序计数器PC保存起来
    1. 引出中断服务程序
      • 取出中断服务程序的入口地址,送去程序技术去PC中
    1. 保存线程和屏蔽字
      • 进入中断程序后,首先保存现场信息:程序状态字寄存器PSWR和某些通用寄存器内容
    1. 开中断
      • 允许更高级别中断请求得到响应
    1. 执行中断服务程序
      • 中断请求的目的就是执行中断服务程序
    1. 关中断
      • 保证在恢复线程和屏蔽字时不被中断
    1. 恢复现场和屏蔽字
      • 将现场和屏蔽字恢复到原来的状态
    1. 开中断、中断返回
      • 中断服务程序的最后一条指令通常是中断返回指令,时期返回原程序断点处,以便继续执行原程序
  • 进程
    • 进程是资源分配的基本单位

    • 进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。

    • 进程的上下文包含的内容:

      • 内存中的程序代码和数据、寄存器内容、程序计数器、环境变量、打开文件的描述符集合
    • 程序段+相关数据段+PCB构成了进程实体

    • 进程的创建(创建原语):

      • 申请一个空白的PCB,每个进程有唯一的进程标识号
      • 为进程分配资源,为新进程的程序和数据以及用户栈分配必要的内存空间
      • 初始化PCB,包括初始化标志信息、初始化处理器状态信息和初始化处理器控制信息,已经设置进程的优先级等
      • 最后把该进程转入就绪态,插入就绪队列,等待被调度
    • 进程的终止(撤销原语):

      • 根据被终止进程的标识符,检索PCB,从中读出该进程的状态
      • 若被终止的进程处于执行状态,立即终止该进程的执行,将处理器资源分配给其他进程
      • 若该进程有子进程,则将所有子进程终止
      • 将该进程所拥有的全部资源,归还给父进程,或归还给操作系统
      • 将该PCB从队列(链表)中删除
    • 进程的阻塞和唤醒

      • 正在执行的进程,由于请求系统资源失败、等待某种操作等,无新工作可做,则系统自动执行阻塞原语(Block),使自己由运行态变为阻塞态

      • 进程的阻塞是进程自身的主动行为,只有处于运行态的进程才能转为阻塞态

      • 当阻塞进程期待的事件发生后,如I/O操作完成,由有关进程(如,释放该I/O设备的进程,或提供数据的进程)调用唤醒原语(Wakeup),将该进程唤醒

      • 阻塞原语:

      • 找到要被阻塞进程的标识号对应的PCB

      • 如果该进程为运行态,则保护其现场,将其状态转为阻塞态,停止运行

      • 将该PCB插入相应事件的等待队列,将处理器资源调度给其他就绪进程

      • 唤醒原语
        • 在该事件的等待队列中找到相应进程的PCB
        • 将其从等待队列中移出,并置为就绪态
        • 将该PCB插入就绪队列,等待调度程序调度
    • 进程切换

    • 进程切换指处理器从一个进程运行转到另一个进程上,进程的运行环境产生了实质的变化,过程如下

      • 保存处理器上下文,包括程序计数器和其他寄存器
      • 保存PCB信息
      • 把进程的PCB移入相应的队列,如就绪队列、在某个事件阻塞队列
      • 选择另一个进程执行,并更新其PCB
      • 更新内存管理的数据结构
      • 恢复处理器上下文
    • 进程切换与处理器模式切换不同

      进程切换:

      ​ 当前运行进程改变了,则当前进程的环境信息也需要改变

    • 处理器模式切换:

      ​ 模式切换时,处理器可能还在同一进程中运行

      ​ 如果进程因中断或异常进入内核态运行,执行完后又回到用户态刚被中断的程序运行

      ​ 这种情况,操作系统只需要恢复进程进入内核时所保存的CPU现场,无须改变当前进程的环境信息

    • 调度和切换的区别:

      • 调度:调度决定资源分配给哪个进程的行为,是一种决策行为
      • 切换:切换指实际分配的行为,是执行行为
      • 一般来说,先有资源的调度,然后才有进程的切换
    • 进程控制块(PCB)

      • PCB是进程实体的一部分,是进程存在的唯一标志
      • 操作系统通过PCB表管理和控制进程
        • 操作系统调度某进程时,会从其PCB中查出其现行状态及优先级,根据PCB中保存的处理器状态信息,设置该进程恢复运行的现场,并根据其PCB中的程序和数据的内存起始地址,找到程序和数据
        • 进程运行时,当需要和合作的进程实现同步、通信或访问文件时,也需要访问PCB
        • 进程由于某种原因而暂停运行时,又需要将其断点的处理器环境保存在PCB中
    • 程序段

      被进程调度程度调度到CPU执行的程序代码段,程序可被多个进程共享,多个进程可运行同一个程序

    • 数据段

      一个进程的数据段,可以实原始数据,也可以是程序执行的中间或最终结果

线程
  • 线程是基本的CPU执行单元,也是程序执行流的最小单元,系统独立调度和分派的基本单位

  • 线程由线程ID、程序计数器、寄存器集合和堆栈组成

  • 进程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但是可与同属于一个进程的其他线程共享所拥有的全部资源

  • 一个线程可以创建和撤销另一个线程

  • 一个进程中可以有多个线程,它们共享进程资源

  • 引入线程后,进程的内涵发生了改变,进程只作为除CPU外的系统资源的分配单元,而线程则作为处理器的分配单元

  • 引入进程的目的是为了更好的使多程序并发执行,提高资源利用率和系统吞吐量;引入线程的目的是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能

  • QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件

    进程和线程的区别
  • 拥有资源

    • 进程是资源分配的基本单位,但是线程不拥有资源(除了一点必不可少的资源),线程可以访问隶属进程的系统资源
    • 如果线程也拥有资源,则切换线程就需要较大的时空开销,线程的概念就没有意义了
  • 调度

    • 传统操作系统中拥有资源和独立调度的基本单位都是进程
    • 引入线程后,线程是独立调度的基本单位,进程是拥有资源的基本单位
    • 在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
  • 系统开销

    • 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。
    • 类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小
    • 同一个进程内的多个线程共享进程的地址空间,因此这些线程间同步与通信非常容易,甚至无须操作系统的干预
  • 并发性:

    • 引入线程后,不仅进程间可以并发执行,而且多个线程之间也可以并发执行,提高了并发性和吞吐量
  • 通信方面

    • 进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间通信可以直接读/写进程数据段(如全局变量)来进行通信
如何选择进程和线程
  • 需要频繁创建销毁的优先用线程

  • 需要进行大量计算的优先使用线程

  • 可能要扩展到多机分布的用进程,多核分布的用线程

    协程
    • 协程,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』,自主开辟的异步任务,具有对内核来说不可见的特性

    • 正如一个进程可以拥有多个线程一样,一个线程也可以拥有多个协程

    • 协程的目的

      • 当出现长时间的I/O操作时,通过让出目前的协程调度,执行下一个任务的方式,减少上下文切换的开销
      • 传统的是,每个请求占用一个线程完成完整的业务逻辑(包括事务),所以系统的吞吐能力取决于每个线程的操作耗时
      • 如果遇到很耗时的I/O行为,则整个系统的吞吐立刻下降,同时,较多的线程会带来很多的上下文切换的开销
      • 由于协程的暂停完全由程序控制,发生在用户态上;而线程的阻塞状态是由操作系统内核来进行切换,发生在内核态上。因此,协程的开销远远小于线程的开销,也就没有了上下文切换上的开销
      协程的特点
    • 线程的切换由操作系统负责调度,协程由用户自己进行调度,因此减少了上下文切换,提高了效率。

    • 线程的默认Stack大小是1M,而协程更轻量,接近1K。因此可以在相同的内存中开启更多的协程。

    • 由于在同一个线程上,因此可以避免竞争关系而使用锁。

    • 适用于被阻塞的,且需要大量并发的场景。但不适用于大量计算的多线程,遇到此种情况,更好用线程解决。

    协程的原理
    • 当出现IO阻塞的时候,由协程的调度器进行调度,通过将数据流立刻yield掉(主动让出),并且记录当前栈上的数据

    • 阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去跑,这样看上去好像跟写同步代码没有任何差别

    • 这整个流程可以称为coroutine,而跑在由coroutine负责调度的线程称为Fiber。比如Golang里的 go关键字其实就是负责开启一个Fiber,让func逻辑跑在上面

    线程协程
    占用资源初始单位为1MB,固定不可变初始一般为 2KB,可随需要而增大
    调度所属由 OS 的内核完成由用户完成
    切换开销涉及模式切换(从用户态切换到内核态)、16个寄存器、PC、SP.等寄存器的刷新等只有三个寄存器的值修改 - PC / SP / DX.
    性能问题资源占用太高,频繁创建销毁会带来严重的性能问题资源占用小,不会带来严重的性能问题
    数据同步需要用锁等机制确保数据的一直性和可见性不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
  • 进程状态的切换

    image.png

    • 创建态(created):进程正在被创建,尚未转到就绪态
    • 就绪状态(ready):进程获取了除处理器以外的一切所需资源,等待被调度,多个处于就绪状态的进程组成就绪队列
    • 运行状态(running):进程正在处理器上运行
    • 阻塞状态(waiting):等待某资源为可用,又称为等待状态,进程正在等待某一事件而暂停运行如等待某资源为可用或等待 IO 操作完成。即使处理器空闲,该进程也不能运行
    • 终止态(terminated):进程正从系统消失,可能是进程正常结束或其他原因中断退出运行

    注意:

    • 只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。
    • 阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。
  • 进程调度
    • 调度:从就绪队列中按照一定的算法选择一个进程并将处理器分配给它运行,以实现进程并发执行

    • 处理器的三级调度

      • 低级调度(进程调度)

        • 最基本的调度,按照某种算法从就绪队列中选取一个进程,并将处理器分配给它
        • 进程调度的频率很高,一般几十毫秒一次
      • 中级调度(内存调度)

        • 作用:提高内存利用率和系统吞吐量
        • 将暂时不能运行的进程调至外存等待,此时的该进程称为挂起态
        • 当其具备运行条件且内存有空闲时,由中级调度将外存上的就绪进程重新调入内存,并修改其状态为就绪态,挂在就绪队列上等待
      • 高级调度(作业调度)

        • 按一定的规则从外存上处于后备状态的作业中挑选一个或多个作业,给它们分配内存、输入输出设备必要的资源,并建立相应的进程
        • 多道批处理系统中大多配有作业调度,而其他系统中通常不需要配置作业调度,作业调度执行频率低,通常几分钟一次
      进程切换
      • 进程切换在调度完成后立刻发生
      • 操作系统内核将原进程的现场信息推入当前进程的内核堆栈来保存它们,并更新堆栈指针
      • 内核完成从新进程的内核栈中装入新进程的现场信息、更新当前运行进程空间指针、重设PC寄存器等工作
      • 开始运行新的进程
    • 不能马上进行调度与切换的情况:

      • 处理中断的过程中:

        中断过程复杂,实现上很难做到进程切换,而中断处理是系统的一部分,逻辑上不属于某一个进程,不应被剥夺处理器资源

      • 进程在操作系统内核程序临界区中:
        进入临界区后,需要独占式访问共享数据,解锁前不应切换到其他进程运行

      • 需要完全屏蔽中断的原子操作过程中:

        加锁、解锁、中断现场保护、恢复等原子操作,中断都要屏蔽,更不应该进行进程调度和切换

      进程调度方式
    • 非剥夺调度方式(非抢占方式):

      一旦把CPU分配给一个进程,该进程会保持CPU直到终止或转换到等待态

      • 优点:系统开销小,适合批处理系统
      • 缺点:不能用于分时系统和实时系统
    • 剥夺调度方式(抢占方式):

      • 当进程正在CPU上执行时,若某个更重要/紧迫的进程需要使用CPU,则立即暂停正在执行的进程,将处理机分配给这个更为重要/紧迫的进程
    • 调度的基本准则

      • CPU利用率:尽可能使CPU利用率最高
      • 系统吞吐量:单位时间内CPU完成作业的数量
      • 周转时间:从作业提交到作业完成所经历的时间
      • 等待时间:进程处于等待CPU状态的时间之和
      • 响应时间:从用户提交到系统首次产生响应所用的时间
  • 进程调度算法
    • 为了确定首先执行哪个进程以及最后执行哪个进程以实现最大 CPU 利用率

      1.批处理系统
      • 批处理系统在很老的计算机时使用,没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)

      1.1 先来先服务 first-come first-serverd(FCFS)

      • 非抢占式的调度算法,按照请求的顺序进行调度
      • 有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长

      1.2 短作业优先 shortest job first(SJF)

      • 非抢占式的调度算法,按估计运行时间最短的顺序进行调度
      • 长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度

      1.3 高响应比优先

      • 高响应比优先调度算法是FCFS和SJF的综合平衡,每次进行作业调度时,先计算后备作业队列中每个作业的响应比,从中选出响应比最高的作业投入运行
      • image.png
      • 要求服务时间短,响应比高,有利于短作业
      • 等待时间长,响应比高,不会出现长作业饿死的情况
      2. 交互式系统
      • 交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。

      2.1 时间片轮转

      • 将所有就绪进程按先到先来原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片

      • 当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程

      • 时间片轮转算法的效率和时间片的大小有很大关系:

        • 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间
        • 如果时间片过长,那么实时性就不能得到保证
      • image.png

      2.2 优先级调度

      • 为每个进程分配一个优先级,按优先级进行调度
      • 为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级

      2.3 多级反馈队列

      • 一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次
      • 多级队列是为这种需要连续执行多个时间片的进程考虑,设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,…。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次
      • 每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列中的进程
      • 可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合

      image.png

      3. 实时系统
      • 实时系统要求一个请求在一个确定时间内得到响应。

      • 分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。

  • 进程间通信的几种方式

    • 进程间通信(IPC,InterProcess Communication)的目的

      • **数据传输:**一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几兆字节之间
      • **共享数据:**多个进程想要操作共享数据,一个进程对共享数据的修改,别的进程应该立刻看到
      • **通知事件:**一个进程需要向另一个或一组进程发送消息,通知它(它们)发生了某种事件(如进程终止时要通知父进程)
      • **资源共享:**多个进程之间共享同样的资源。为了作到这一点,需要内核提供锁和同步机制
      • **进程控制:**有些进程希望完全控制另一个进程的执行(如Debug进程),此时控制进程希望能够拦截另一个进程的所有陷入和异常,并能够及时知道它的状态改变

      IPC方式包括:

      1.管道(pipe)
      • 管道的特点:

        • 管道是半双工,数据只能向一个方向流动;双方需要互相通信时,需要建立起两个管道
        • 只能用于具有亲缘关系的进程(父子进程或者兄弟进程)之间
        • 管道对于两端通信的进程来说就只是一种文件,一种不属于文件系统仅存在内存中的“伪文件”
        • 管道的通信方式为:写端每次都将数据写入管道缓冲区的 末尾 ,而读端每次都从管道缓冲区的 头部 读出数据
        • 当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开,要关闭管道只需将这两个文件描述符关闭即可。如下图:
      • image.png

      • 管道的实质

        • 管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据:管道一端的进程顺序地将进程数据写入缓冲区,另一端的进程则顺序地读取数据
        • 该缓冲区可以看做一个循环队列,读和写的位置都是自动增加的,一个数据只能被读一次,读出以后再缓冲区都不复存在了
        • 当缓冲区读空或者写满时,有一定的规则控制相应的读进程或写进程是否进入等待队列,当空的缓冲区有新数据写入或慢的缓冲区有数据读出时,就唤醒等待队列中的进程继续读写
      2.信号(signals)
      • 信号的特点:

        • Unix系统中使用的最古老的进程间通信的方法之一,操作系统通过信号来通知进程系统中发生了某种预先规定好的事件(一组事件中的一个),它也是用户进程之间通信和同步的一种原始机制
        • 一个键盘中断或者一个错误条件(比如进程试图访问它的虚拟内存中不存在的位置等)都有可能产生一个信号
        • 信号可以在任何时候发给某一进程,而无需知道该进程的状态
        • 对信号的任何处理,包括终止进程,都必须由接收到信号的进程真正执行时才能处理,所以信号处理可能需要延迟一段时间
        • 如果该进程当前并未处于执行状态,则内核保存该信号,直到该进程回复执行并传递给它为止
      • 信号的来源:

        • 信号是软件层次上对中断机制的一种模拟,是一种异步通信方式(所以信号不是中断,信号处理程序在用户态下运行的, 中断程序在核心态下运行的)

        • 信号可以在用户空间进程和内核之间直接交互,内核可以利用信号来通知用户空间的进程发生了哪些系统事件

        • 信号事件主要有两个来源:

          • 硬件来源:用户按键输入 Ctrl+C 退出、硬件异常如无效的存储访问等
          • 软件终止:终止进程信号、其他进程调用 kill 函数、软件异常产生信号
      • 信号生命周期和处理流程

        信号被某个进程产生,并设置此信号传递的对象(一般为对应进程的pid),然后传递给操作系统

        操作系统根据接收进程的设置(是否阻塞)而选择性的发送给接收者,如果接收者阻塞该信号(且该信号是可以阻塞的),操作系统将暂时保留该信号,而不传递,直到该进程解除了对此信号的阻塞(如果对应进程已经退出,则丢弃此信号),如果对应进程没有阻塞,操作系统将传递此信号

        目的进程接收到此信号后,将根据当前进程对此信号设置的预处理方式,暂时终止当前代码的执行,保护上下文(主要包括临时寄存器数据,当前程序位置以及当前CPU的状态)、转而执行中断服务程序,执行完成后在回复到中断的位置。当然,对于抢占式内核,在中断返回时还将引发新的调度;

      3…消息队列(message)
      • 消息队列的特点:

        • 消息队列是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识
        • 消息队列克服了信号传递信息少,管道只能承载无格式字节流以及缓冲区受限等特点
        • 消息队列允许一个或多个进程向它写入与读取消息
        • 管道和消息队列的通信数据都是先进先出的原则
        • 与管道相比,管道发送的数据没有类型;消息队列有类型,读端可以根据数据类型读取特定的数据
      4.共享内存(share memory)
      • 使得多个进程可以直接读写同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的
      • 为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率
      • 信号量+共享内存通常结合在一起使用,信号量用来同步对共享内存的访问
      5.信号量(semaphore)
      • 信号量

        信号量是一个计数器,用于多进程对共享数据的访问,信号量的意图在于进程间同步

      • 信号量与普通整型变量的区别:

        • 信号量是非负整型变量,除了初始化之外,它只能通过两个标准原子操作:wait(semap) , signal(semap) ; 来进行访问
        • 操作也被成为PV原语,而普通整型变量则可以在任何语句块中被访问
      6.套接字(socket)
      • 适合同一主机的不同进程间不同主机的进程间进行全双工网络通信,此方法主要用于在客户端和服务器之间通过网络进行通信。套接字是支持 TCP/IP 的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
  • 同步与互斥的区别与联系
    • 互斥:是指散布在不同进程(线程)之间的若干程序片断,当某个进程(线程)运行其中一个程序片段时,其它进程(线程)就不能运行它们之中的任一程序片段,只能等到该进程(线程)运行完这个程序片段后才可以运行。
    • 同步:是指散布在不同进程(线程)之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。

    同步是一种更为复杂的互斥,而互斥是一种特殊的同步。也就是说互斥是两个线程之间不可以同时运行,他们会相互排斥,必须等待一个线程运行完毕,另一个才能运行,而同步大部分情况下也是不能同时运行,但他是必须要安照某种次序来运行相应的线程,而且少数时候同步可以允许多个线程同时运行!

  • 进程同步的几种方式
    1. 临界区
    • 对临界资源进行访问的那段代码称为临界区。
    • 为了互斥访问临界资源,每个进程在进入临界区之前,需要先进行检查。
    1. 同步与互斥
    • 同步:多个进程因为合作产生的直接制约关系,使得进程有一定的先后执行关系。
    • 互斥:多个进程在同一时刻只有一个进程能进入临界区。
    1. 信号量
    • 信号量(Semaphore)是一个整型变量,可以对其执行 down 和 up 操作,也就是常见的 P 和 V 操作。

      • down : 如果信号量大于 0 ,执行 -1 操作;如果信号量等于 0,进程睡眠,等待信号量大于 0;

      • up :对信号量执行 +1 操作,唤醒睡眠的进程让其完成 down 操作。

      • down 和 up 操作需要被设计成原语,不可分割,通常的做法是在执行这些操作的时候屏蔽中断

      • 如果信号量的取值只能为 0 或者 1,那么就成为了 互斥量(Mutex) ,0 表示临界区已经加锁,1 表示临界区解锁

  • 线程间同步的方式

    线程间同步的方式主要由以下三种:

    • 互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
    • 信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。
    • 事件(信号):通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。即事件机制允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。
  • 操作系统的内存管理机制

    • 简单分为连续分配管理方式非连续分配管理方式这两种。
      • 连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如块式管理
      • 非连续分配管理方式允许一个程序使用的内存分布在离散或者说不相邻的内存中,常见的如页式管理段式管理
    • 块式管理 : 远古时代的计算机操系统的内存管理方式。将内存分为几个固定大小的块,每个块中只包含一个进程。如果程序运行需要内存的话,操作系统就分配给它一块,如果程序运行只需要很小的空间的话,分配的这块内存很大一部分几乎被浪费了。这些在每个块中未被利用的空间,我们称之为碎片。
    • 页式管理 :把主存分为大小相等且固定的一页一页的形式,相对相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。页式管理通过页表对应逻辑地址和物理地址。
    • 段式管理 : 页式管理虽然提高了内存利用率,但是页式管理其中的页实际并无任何实际意义。 段式管理把主存分为一段段的,每一段的空间又要比一页的空间小很多 。但是,最重要的是段是有实际意义的,每个段定义了一组逻辑信息,例如,有主程序段 MAIN、子程序段 X、数据段 D 及栈段 S 等。 段式管理通过段表对应逻辑地址和物理地址。
    • 段页式管理机制 :结合了段式管理和页式管理的优点。程序的地址空间划分成多个拥有独立地址空间的段,每个段上的地址空间划分成大小相同的页。这样既拥有分段系统的共享和保护,又拥有分页系统的虚拟内存功能。
    • 分页,分段,段页的区别
      • 对程序员的透明性:分页透明,但是分段需要程序员显式划分每个段
      • 地址空间的维度:分页是一维地址空间,分段是二维的
      • 大小是否可以改变:页的大小不可变,段的大小可以动态改变
      • 出现的原因:分页主要用于实现虚拟内存,从而获得更大的地址空间;分段主要是为了使程序和数据可以被划分为逻辑上独立的地址空间并且有助于共享和保护
  • 页面置换算法

    在程序运行过程中,如果要访问的页面不在内存中,就发生缺页中断从而将该页调入内存中此时如果内存已无空闲空间,系统必须从内存中调出一个页面到磁盘对换区中来腾出空间

    • 最佳页面置换算法:所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。但由于人们目前无法预知进程在内存下的若千页面中哪个是未来最长时间内不再被访问的,因而该算法无法实现。一般作为衡量其他置换算法的方法。
    • 先进先出页面置换算法: 总是淘汰最先进入内存的页面,即选择在内存中驻留时间最久的页面进行淘汰。实现简单,但性能很差。
    • 最近最久未使用页面置换算法:优先淘汰最近最久没访问的页面,赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 T,当须淘汰一个页面时,选择现有页面中其 T 值最大的。性能很好,但需要硬件支持,算法开销大。
    • 时钟置换算法 : 该置换算法选择在之前时期没有被访问过的页面作为淘汰页。为每个页面设置一个访问位,再将内存中的页面都通过链接指针链接成一个循环队列。当某个页被访问时,其访问位置1.当需要淘汰一个页面时,只需检查页的访问位。如果是0,就选择该页换出;如果是1,暂不换出,将访问位改为0,继续检查下一个页面,若第一轮扫描中所有的页面都是1,则将这些页面的访问位一次置为0后,再进行第二轮扫描(第二轮扫描中一定会有访问位为0的页面,因此简单的CLOCK算法选择一个淘汰页面最多会经过两轮扫描
  • OS死锁相关的问题
    • 是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。 因此我们举个例子来描述,如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁。

    • 对不可剥夺资源的不合理分配,可能导致死锁。

    • 预防死锁:破坏死锁产生的四个必要条件

    • 避免系统:避免系统进入不安全状态(银行家算法)

    • 死锁必须同时满足以下四个条件,只要其中任一条件不成立,死锁就不会发生。

      • 互斥条件:进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。
      • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。
      • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
      • 循环等待条件:存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被链中下一个进程所请求。
    • 预防死锁:破坏死锁产生的四个必要条件
      1. 破坏互斥条件

      如果允许系统资源都能共享使用,则系统不会进入死锁状态。但有些资源根本不能同时访问,如打印机等临界资源只能互斥使用。所以,破坏互斥条件而预防死锁的方法不太可行,而且在有的场合应该保护这种互斥性。

      1. 破坏不剥夺条件

      当一个已保持了某些不可剥夺资源的进程,请求新的资源而得不到满足时,它必须释放已经保持的所有资源,待以后需要时再重新申请。这意味着,一个进程已占有的资源会被暂时释放,或者说是被剥夺了,或从而破坏了不可剥夺条件。

      该策略实现起来比较复杂,释放已获得的资源可能造成前一阶段工作的失效,反复地申请和释放资源会增加系统开销,降低系统吞吐量。这种方法常用于状态易于保存和恢复的资源,如CPU的寄存器及内存资源,一般不能用于打印机之类的资源。

      1. 破坏请求和保持条件

      釆用预先静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不把它投入运行。一旦投入运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。

      这种方式实现简单,但缺点也显而易见,系统资源被严重浪费,其中有些资源可能仅在运行初期或运行快结束时才使用,甚至根本不使用。而且还会导致“饥饿”现象,当由于个别资源长期被其他进程占用时,将致使等待该资源的进程迟迟不能开始运行。

      1. 破坏循环等待条件

      为了破坏循环等待条件,可釆用顺序资源分配法。首先给系统中的资源编号,规定每个进程,必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源Ri,则该进程在以后的资源申请中,只能申请编号大于Ri的资源。

      这种方法存在的问题是,编号必须相对稳定,这就限制了新类型设备的增加;尽管在为资源编号时已考虑到大多数作业实际使用这些资源的顺序,但也经常会发生作业使甩资源的顺序与系统规定顺序不同的情况,造成资源的浪费;此外,这种按规定次序申请资源的方法,也必然会给用户的编程带来麻烦。

      死锁避免

      ​ 避免死锁同样是属于事先预防的策略,但并不是事先釆取某种限制措施破坏死锁的必要条件,而是在资源动态分配过程中,防止系统进入不安全状态,以避免发生死锁。这种方法所施加的限制条件较弱,可以获得较好的系统性能。

      系统安全状态

      ​ 避免死锁的方法中,允许进程动态地申请资源,但系统在进行资源分配之前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源分配给进程; 否则,让进程等待。

      ​ 所谓安全状态,是指系统能按某种进程推进顺序( P1, P2, …, Pn),为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺序地完成。此时称 P1, P2, …, Pn 为安全序列。如果系统无法找到一个安全序列,则称系统处于不安全状态。

      银行家算法

      ​ 算法思路

      • 背景
        将操作系统视为银行家,操作系统管理的资源视为银行家管理的资金,进程向操作系统申请资源视为客户向银行家贷款,客户在首次申请贷款时声明最大贷款额度,此后分期向银行家贷款,以后每次向银行家贷款累积不超过首次申请贷款时声明的最大贷款额度,银行家将在自己资金允许的范围内尽可能满足客户的要求,直到满足客户最大需求,客户归还资金。
      • 思路
        进程首次申请资源时声明最大资源需求量,此后每次向操作系统申请的资源总和不得超过最大需求量,否则操作系统将拒绝分配,若未超过,操作系统将查询当前资源是否符合需求,若符合需求则分配,否则进程等待。
      • 核心
        安全性算法
        保证系统不会进入不安全状态,即系统任意时刻可用资源能够至少可以满足一个进程最大需求量并使得其完成
      数据结构
      • 可利用资源向量Available
        m维数组,每个元素代表一类资源的当前可用数目,初始值为系统所拥有的该类的全部资源,Available[j] = K表示当前R[j]类资源有K个
      • 最大需求矩阵Max
        n * m矩阵,定义系统中n个进程中的每个进程对m类资源的最大需求量,Max[i][j] = K表示进程P[i]需要R[j]类的最大数目为K
      • 分配矩阵Allocation
        n * m矩阵,定义系统中n个进程中的每个进程对m类资源的当前持有数目,Allocation[i][j] = K表示当前进程P[i]已占有资源K个
      • 需求矩阵Need
        n * m矩阵,定义系统中n个进程中的每个进程对m类资源还需申请的数目,Need[i] = K表示还需要R[j]类资源K个
      • 上述三矩阵满足下列关系
        Need[i][j] = Max[i][j] - Allocation[i][j]
      算法描述
      • 请求向量Request
        进程P[i]向操作系统申请的资源数量,Request[i][j] = K表示进程P[i]需要R[j]类资源K个
      • 是否超过最大需求量
        Request[i][j] ≤ Need[i][j]则进行下一步判断,否则超过声明的最大需求量,操作系统拒绝分配
      • 是否存在足够可用资源
        Request[i][j] ≤ Available[i][j]则进行下一步操作,否则进程P[i]等待
      • 系统试探着分配资源给进程P[i],并修改对应数据结构
        Available[j] = Available[j] - Request[i][j];
        Allocation[i][j] = Allocation[i][j] + Request[i][j];
        Need[i][j] = Need[i][j] - Request[i][j];
      • 最后执行安全性算法,检查此次资源分配后,系统是否处于安全状态1,若安全完成分配,否则本次分配作废,恢复原来的分配状态2
      安全性算法
      1. 初始时安全序列为空3
      2. 从Need矩阵中找到对应进程不再安全序列中且小于等于Available向量的 行,对应进程加入安全序列,若找不到调转到第四步
      3. 进程P[i]进入安全序列后执行至完成,释放占有的资源,执行Available = Available + Allocation[i],返回第二步
      4. 若此时安全序列中已有所有进程,则系统处于安全序列,否则系统处于不安全状态
      死锁的检测和解除

      若系统为进程分配资源时不釆取任何措施,则应该提供死锁检测和解除的手段。

      资源分配图

      系统死锁,可利用资源分配图来描述。如下图所示,用圆圈代表一个进程,用框代表一类资源。由于一种类型的资源可能有多个,用框中的一个点代表一类资源中的一个资源。从进程到资源的有向边叫请求边,表示该进程申请一个单位的该类资源;从资源到进程的边叫分配边,表示该类资源已经有一个资源被分配给了该进程。

      img

      ​ 资源分配示例图

      在资源分配图中,进程P1已经分得了两个R1资源,并又请求一个R2 资源;进程P2分得了一个R1和一个R2资源,并又请求一个R1资源。

      死锁定理

      可以通过将资源分配图简化的方法来检测系统状态S是否为死锁状态。简化方法如下:

      1. 在资源分配图中,找出既不阻塞又不是孤点的进程Pi(即找出一条有向边与它相连,且该有向边对应资源的申请数量小于等于系统中已有空闲资源数量。若所有的连接该进程的边均满足上述条件,则这个进程能继续运行直至完成,然后释放它所占有的所有资源)。消去它所有的请求边和分配边,使之成为孤立的结点。在图2-18(a)中,P1是满足这一条件的进程结点,将P1的所有边消去,便得到图248(b)所示的情况。

      2. 进程Pi所释放的资源,可以唤醒某些因等待这些资源而阻塞的进程,原来的阻塞进程可能变为非阻塞进程。在图2-17中,进程P2就满足这样的条件。根据第1) 条中的方法进行一系列简化后,若能消去图中所有的边,则称该图是可完全简化的,如图2-18©所示。

      S为死锁的条件是当且仅当S状态的资源分配图是不可完全简化的,该条件为死锁定理。

      死锁的解除

      一旦检测出死锁,就应立即釆取相应的措施,以解除死锁。死锁解除的主要方法有:

      1. 资源剥夺法。挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源,而处于资源匮乏的状态。

      2. 撤销进程法。强制撤销部分、甚至全部死锁进程并剥夺这些进程的资源。撤销的原则可以按进程优先级和撤销进程代价的高低进行。

      3. 进程回退法。让一(多)个进程回退到足以回避死锁的地步,进程回退时自愿释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。

  • 磁盘调度算法
    • 读写一个磁盘块的时间的影响因素有:

      • 旋转时间(主轴转动盘面,使得磁头移动到适当的扇区上)
      • 寻道时间(制动手臂移动,使得磁头移动到适当的磁道上)
      • 实际的数据传输时间
    • 其中,寻道时间最长,因此磁盘调度的主要目标是使磁盘的平均寻道时间最短。

    先来先服务
    • 按照磁盘请求的顺序进行调度。

    • 优点是公平和简单。缺点也很明显,因为未对寻道做任何优化,使平均寻道时间可能较长。

    最短寻道时间优先
    • 优先调度与当前磁头所在磁道距离最近的磁道,可以保证每次的寻道时间最短,但是并不能保证总的寻道时间最短。
    • 虽然平均寻道时间比较低,但是不够公平。如果新到达的磁道请求总是比一个在等待的磁道请求近,那么在等待的磁道请求会一直等待下去,也就是出现饥饿现象
    扫描算法

    为了防止饥饿的问题规定,只有磁头移动到最外侧磁道的时候才能往内移动,移动到最内侧磁道的时候才能往外移动。这就是扫描算法(SCAN)的思想。由于磁头移动的方式很像电梯,因此也叫电梯算法

    • 优点:

      • 性能较好,平均寻道时间较短,不会产生饥饿现象。
    • 缺点:

      • 只有到达最边上的磁道时才能改变磁头移动方向。
      • SCAN算法对于各个位置磁道的响应频率不平均。
    电梯算法(扫描算法)
    • 电梯总是保持一个方向运行,直到该方向没有请求为止,然后改变运行方向。
    • 电梯算法和电梯的运行过程类似,总是按一个方向来进行磁盘调度,直到该方向上没有未完成的磁盘请求,然后改变方向。
    • 因为考虑了移动方向,因此所有的磁盘请求都会被满足,解决了最短寻道时间优先的饥饿问题。
    LOOK调度算法

    如果在磁头移动方向上已经没有别的请求,就可以立即改变磁头移动方向。(边移动边观察,因此叫LOOK)

    优点: 比起SCAN算法来,不需要每次都移动到最外侧或最内侧才改变磁头方向,使寻道时间进步缩短。

    循环扫描算法( C-SCAN)

    SCAN算法对于各个位置磁道的响应频率不平均,而 C-SCAN算法就是为了解决这个问题。规定只有磁头朝某个特定方向移动时才处理磁道访问请求,而返回时直接快速移动至起始端而不处理仼何请求。

    优点: 比起SCAN来,对于各个位置磁道的响应频率很平均。

    缺点: 只有到达最边上的磁道时才能改变磁头移动方向。

    C-LOOK调度算法

    C-SCAN算法的主要缺点是只有到达最边上的磁道时才能改变磁头移动方向,并且磁头返回时不一定需要返回到最边缘的磁道上。 C-LOOK算法就是为了解决这个问题。如果磁头移动的方向上已经没有磁道访问请求了,就可以立即让磁头返回,并且磁头只需要返回到有磁道访问请求的位置即可。

    优点: 比起 C-SCAN算法来,不需要每次都移动到最外侧或最内侧才改变磁头方向,使寻道时间进一步缩短。

    3.linux中几种io模型 (select,poll,epoll)

    10.动态链接库与静态链接库的区别

  • 几种IO模型

  • 虚拟内存技术

    传统管理方式特征
    传统存储管理方式具有一次性驻留性的特点。

    • 一次性:作业必须一次性装入内存后才可以开始运行
    • 驻留性:作业被装入内存后,就一直驻留在内存中,其任何一部分都不会被换出,直至作业运行结束
    问题
    • 程序通常具有异常错误条件的代码,而这些错误很少发生,所以这些代码几乎从不执行
    • 数组、链表等所分配的内存量通常多于实际需要值
    • 程序的某些选项和功能很少使用
    • 当作业很大而不能全部被装入内存时,该作业无法运行
    • 大量作业要求运行时,由于内存不足以容纳所有作业,只能使少数作业先运行,导致多道程序度下降
    局部性原理

    局部性原理从广义角度上讲属于高速缓存技术,而高速缓存技术依赖于局部性原理,局部性原理主要表现在时间局部性和空间局部性

  • 时间局部性
    程序中某条执行一旦执行,不久后可能再次执行,某数据一般被访问,不久后可能还会被访问,产生局部性的典型原因是程序中存在大量的循环。

  • 空间局部性
    一旦程序访问了某个存储单元,不久后其附近的存储单元也将被访问,主要原因是指令通常是`顺序存放和顺序执行的,数据也一般是以向量、数组、表等形式簇聚形式存储的。

    虚拟内存技术
  • 虚拟内存
    虚拟内存技术允许执行进程不必完全处于内存中,虚拟内存将内存抽象成一个巨大的、统一的存储数组,实现了逻辑内存和物理内存的分离,让用户看到的比实际内存大得多的内存空间。

  • 优点

    • 程序不再受物理可用量限制
    • 可以同时运行更多的程序
    • 加载或交换每个用户程序到内存所需的I/O会更少
  • 特征

    • 多次性:无需再作业运行时一次性全部转入内存,允许被分成多次调入内存运行
    • 对换性:无需在作业运行时一直常驻内存,允许在作业的运行过程中,进行换入和换出
    • 虚拟性:逻辑上扩充内存容量,使用户看到的内存容量远大于实际内存容量
    虚拟内存技术实现
  • 基础:虚拟内存技术的实现建立在离散分配的内存管理方式的基础上

  • 方式

    • 请求分页存储管理 :建立在分页管理之上,为了支持虚拟存储器功能而增加了请求调页功能和页面置换功能。请求分页是目前最常用的一种实现虚拟存储器的方法。请求分页存储管理系统中,在作业开始运行之前,仅装入当前要执行的部分段即可运行。假如在作业运行的过程中发现要访问的页面不在内存,则由处理器通知操作系统按照对应的页面置换算法将相应的页面调入到主存,同时操作系统也可以将暂时不用的页面置换到外存中。
    • 请求分段存储管理 :建立在分段存储管理之上,增加了请求调段功能、分段置换功能。请求分段储存管理方式就如同请求分页储存管理方式一样,在作业开始运行之前,仅装入当前要执行的部分段即可运行;在执行过程中,可使用请求调入中断动态装入要访问但又不在内存的程序段;当内存空间已满,而又需要装入新的段时,根据置换功能适当调出某个段,以便腾出空间而装入新的段。
    • 请求段页存储管理
    • 不管是上面那种实现方式,一般都需要:
      • 一定容量的内存和外存:在载入程序的时候,只需要将程序的一部分装入内存,而将其他部分留在外存,然后程序就可以执行了;
      • 缺页中断**:如果需执行的指令或访问的数据尚未在内存(称为缺页或缺段),则由处理器通知操作系统将相应的页面或段调入到内存,然后继续执行程序;**
      • 虚拟地址空间 :逻辑地址到物理地址的变换。
      • 页表或段表机制,作为主要数据结构
    请求调页

    请求调页只要将当前需要的一部分页面装入内存,即可启动作业运行

    页表机制

    请求分页在一个作业运行之前不要求全部一次性调入内存,故在作业运行过程中,必然会出现要访问的页面不再主存中的情况,故除了页号和对应物理页号,还需在请求页表项中添加4个字段。

    • 状态位,用于指示该页是否已经调入内存,供出现访问时参考
    • 访问字段,记录本页在一段时间内被访问的次数,供置换算法换出页面时参考
    • 修改位,标识改页是否被修改过
    • 外存地址,指向该页在外存的地址,通常是物理块号,供调入该页时参考
    缺页中断机构

    若进程所要访问的页面不再主存中,则会产生缺页中断,进行缺页处理。缺页中断作为中断同样要经历保护现场、分析中断原因、进入缺页中断处理程序、中断返回、恢复现场等步骤,但与一般中断不同的是,缺页中断在指令执行期间而非指令执行完后产生和处理中断信号,属于内部中断,一条指令在执行期间可能出现多次缺页中断。

    地址变换机构

    进行地址变换时,先访问块表

    • 若找到要访问的页的页表项,则修改页表项中的访问位,然后利用页表项中的物理块号和页内偏移地址形成物理地址。
    • 若未找到要访问的页的页表项,则到主存中查找页表,查看页表项中的状态位,若对应页面已经调入主存,则进行访问,否则产生缺页中断,进行缺页处理。
  • 什么是缓冲区溢出。有什么危害,其原因是什么

  • Linux系统常用的命令有哪些?

    • 查看进程命令

      1. ps命令

      (1)不带参数—ps

      功能:查询在当前控制台上运行的进程。

      **(**2)查看所有进程—ps -aux

      功能:查询系统中所有运行的进程,包括后台进程,其中参数a是所有进程,参数x包括不占用控制台的进程,参数u显示用户。

      (3)查看所有进程—ps -ef

      功能:查询系统中所有运行的进程,包括后台进程,而且可以显示出每个进程的父进程号。

      2. pstree命令

      (1)树状格式显示进程列表----pstree

      功能:以树状格式显示系统的进程列表。

      (2)带进程号的树状格式显示进程列表—pstree -p

      功能:以树状格式显示系统的进程列表,并标识出每个进程的进程号

      3. top命令

      [user1@server2 ~]# top

      功能:动态地显示系统中的进程。可以看到总体的系统运行状态和cpu的使用率 。

      top-H

      显示一个线程

      top-

      4. kill命令

      (1)杀掉指定进程—kill 3029

      **功能:**kill命令可以杀掉一个进程,当然普通用户只能杀掉自己的进程。

      **说明:**上述命令中3029是进程号;一般在执行kill命令之前,先用ps或pstree来查询一下将要被杀掉的进程的进程号。

      (2)强制杀掉指定进程—kill -9 3029

      功能:强制终止3029号进程的运行,其中参数9代表强制的意思。

      **说明:**实际上kill命令是向该进程发送信号,该进程接到信号后决定是否停止运行,有些守护进程必须要收到参数9才终止运行。

      5.ls命令

      ls命令的功能是显示指定目录下的文件目录清单相当于dos下的dir命令,而且其参数更加丰富多样。

      (1)不带参数—ls

      功能:显示指定目录中的文件清单,如果没有指定任何目录,则默认为当前目录。

      (2)显示隐含文件— ls -a

      功能:显示隐含文件–a。

      说明:若文件名以“.”开头,则认为是隐含的。

      (3)长格式输出—ls -l

      参数-l 的功能是:以长格式列表输出指定目录中的文件清单。

      6.pwd命令

      功能:显示当前目录

      7. mkdir命令

      功能:创建目录。

    8.查看磁盘情况

    Linux 查看磁盘空间可以使用 df 和 du 命令。

    df
    df 以磁盘分区为单位查看文件系统,可以获取硬盘被占用了多少空间,目前还剩下多少空间等信息。

    du
    du 含义为显示磁盘空间的使用情况,用于查看当前目录的总大小。

    du -sh–查看当前目录的大小
  • select、poll、epoll

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值