操作系统杂项

用户态切换到内核态的三种方式

1.系统调用:用户态主动要求切换到内核态,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现。

2.异常:当CPU在执行用户态程序时候,发生了异常,这时候会触发由当前运行进程切换到处理此异常的内核相关程序中,也就是转到了内核态(缺页异常)。

3.中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

操作系统锁相关

原子操作原子操作是指不会被线程调度机制打断的操作,这种操作一旦开始就一直运行到结束,原子操作执行过程中禁止中断。

临界区(一段代码):指的是一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性,通过锁机制实现某个时间点上只有一个线程进入临界区代码。

同步:多个进程因为合作关系产生的直接制约关系,进程有先后执行顺序。

互斥:多个进程在同一时刻只有一个进程能进入临界区。

操作系统中的锁机制:

互斥锁:mutex,用于保证在任何时刻,都只能有一个线程访问该对象,只有拥有互斥锁的进程才能进入临界区。

读写锁:rwlock,读写锁根据进程的具体行为决定锁的占用,无锁,所有都可以进入,读锁,只可以读不可以写,写锁,读写都不被允许。

自旋锁:spinlock:如果进程获得锁失败则进行忙等待而不是阻塞,这样如果在时间片内拿到了锁就减少了一个上下文切换的时间(需要多处理器,否则会空转)

RCU:read-copy-update:在修改数据的时候,生成一个数据的副本,对副本进行修改,然后update新的数据。不用考虑死锁问题,大量读少量写的情况下效率非常高。

中断

以前计算机只能串行执行,后来引入了中断,实现了多道程序的并发执行,中断是并发的前提条件。

  1. 当一个时间片运行完后,CPU会接收到计时部件(操作系统内核的时钟管理部件)发出的中断信号,CPU立即进入核心态,把CPU的使用权限交还给操作系统
  2. 当中断发生后,当前运行的进程暂停运行,操作系统内核对中断进程处理,切换进程(根据进程调度算法),在完成切换进程的一系列工作后,操作系统又会将CPU的使用权交还给用户进程
  3. 切换到的进程2拿到CPU执行权就会在用户态下执行

中断的本质发生中断就意味着需要操作系统介入,开展管理工作

中断的处理过程

1.执行完每个指令后,CPU都要检查当前是否有外部中断信号

2.如果检测到外部中断信号,则需要保护被中断进程的CPU环境如程序状态字PSW、程序计数器、各种通用寄存器

3.根据中断信号类型转入相应的中断处理程序

4.恢复进程的CPU环境并退出中断,返回原进程继续往下执行

中断的分类

中断分为内中断和外中断

内中断:来自于CPU内部,与当前执行的指令有关,比如除以0

外中断:来自于CPU外部,与当前执行指令无关,比如用户强制结束一个进程,IO设备中断信号。

缺页中断的过程

1.保护CPU现场

2.分析中断原因

3.转入缺页中断处理程序进行处理

4.恢复现场。

临界资源:一段时间内只允许一个线程访问的资源

信号量PV

允许同一时刻多个线程来访问同一个资源,但是需要控制同一时刻访问此资源的最大线程数量。

信号量的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程,信号量的值与相应资源的使用情况有关,当它的值大于0时,表示当前可用资源的数量,当它的值小于0时,其绝对值表示等待使用该资源的进程个数。

p操作(wait):申请一个资源

v操作(signal):释放一个资源

进程

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

创建态:进程正在被创建。

就绪态:进程已经处于准备运行状态,获得了除了CPU以外的所有资源。

运行态:进程正在CPU上运行。

阻塞态:进程正在等待某一资源而处于等待状态,即使CPU空闲也不能运行。

结束态:进程正在从系统中消失。

只有就绪态和运行态可以相互转换,其他都是单向转换。

挂起态:进程被兑换到辅助存储,不能直接被调度,只有当主存中没有活跃的就绪态进程,或者是当前挂起的进程有更高优先级,系统将会把挂起就绪态的进程调回主存中并且转换为就绪态。

管程

与PV类似,但是管程把控制代码独立出来,封装了同步操作,对进程隐蔽了同步细节,简化了同步功能的调用界面。

管程:在一个时刻只能有一个进程使用管程,进程在无法继续执行的时候不能一直占用管程,否则其他进程永远不能使用管程。

管程引入了条件变量:wait和signal来实现同步操作,wait导致进程阻塞让出管程,signal唤醒。

常见的进程间的通信方式(IPC)

进程间通信需要IPC,线程间通信通过读写同一进程中的数据进行通信。

管道:用于具有亲缘关系的父子进程之间的通信。

linux系统执行命令时,将一个程序的输出交给另一个程序处理,一个进程往管道输入数据,就会阻塞等待其余进程从管道读取数据,管道通过pipe函数创建 fd[0]用于读,fd[1]用于写。

​ 管道的限制:只能支持半双工通信,之恩给你在父子进程或者兄弟进程中使用。

命名管道(FIFO):

将管道命名,允许无沁园进程之间的通信。

信号(Signal):

信号是在软件层次上对中断机制的一种模拟,一种比较复杂的通信方式,用于通知接收进程某个事件已经发生,一个进程收到一个信号与处理器收到一个中断效果一致。

消息队列:提供了一个进程向另一个进程发送数据块的方法

消息队列相对于命名管道:可以独立于读写进程存在,避免了FIFO中同步管道打开和关闭的时候的困难,避免了FIFO的同步阻塞问题,不需要进程自己提供同步方法,读进程可以根据类型有选择的接收消息。

缺点:会收到数据块最大长度的限制,如果频繁发生通信则进程需要频繁读取,很花费时间。

共享内存:共享内存可以解决拷贝消耗的时间

允许多个进程共享一个给定的内存区,不同进程可以及时看到对方进程中对共享内存中数据变更,应为数据不需要在进程之间复制,这是最快的IPC。

共享内存需要依靠同步操作,比如互斥锁和信号量,需要使用信号量用来同步对共享存储的访问。

可以让两个进程各自拿出一块虚拟地址空间,映射到相同的物理内存中,这样两个进程有独立的虚拟内存空间,却有一部分是共享的物理内存。

信号量(mutex):为了避免共享内存多进程竞争内存的问题(线程安全),使用信号量。

信号量的本质就是一个计数器,用来实现进程之间的互斥与同步用于为多个进程提供对共享数据对象的访问,信号量也是进程之间的一种通信方式。

Socket:Socket套接字进行通信,与其他机制不同的是,它可用于不同机器之间的进程间通信,应用非常广泛。

进程的调度

一、批处理系统

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

先来先服务调度算法(FCFS):

  • 每次调度是从就绪队列中选择一个最先进入该队列的进程,为之分配处理机,使之投入运行。该进程一直运行到完成或发生某事件而阻塞后才放弃处理机。
  • 比较有利于长作业(进程),而不利于短作业(进程)
  • 有利于CPU繁忙型作业(进程) ,而不利于I/O繁忙型作业(进程)
  • 用于批处理系统,不适于分时系统

短进程优先调度算法

  • 从就绪队列中选出一个估计运行时间最短的进程,将处理机分配给它,使它立即执行并一直执行到完成,或发生某事件而被阻塞放弃处理机时再重新调度。
  • 对长作业不利,未考虑作业(进程)的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理

最短剩余时间优先 shortest remaining time next(SRTN)

  • 最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。

二、交互式系统

交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应

时间片轮转法

  • 系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片。当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便据此信号来停止该进程的执行,并将它送往就绪队列的末尾;然后,再把处理机分配给就绪队列中新的队首进程,同时也让它执行一个时间片
  • 紧迫任务响应慢。

多级反馈队列调度算法

  1. 设置多个就绪队列,并为各个队列赋予不同的优先级;该算法赋予各个队列中进程执行时间片的大小也各不相同,在优先权愈高的队列中,为每个进程所规定的执行时间片就愈小
  2. 当一个新进程进入内存后,首先将它放入第一队列的末尾按FCFS原则排队等待调度;当轮到该进程执行时,如它能在该时间片内完成,便可准备撤离系统;如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾再同样地按FCFS原则等待调度执行
  3. 仅当第一队列空闲时,调度程序才调度第二队列中的进程运行

优先权调度算法把处理机分配给就绪队列中优先权最高的进程

  • 非抢占式优先权算法:系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成;
  • 抢占式优先权调度算法:系统把处理机分配给优先权最高的进程,使之执行。但在其执行期间只要出现了另一个其优先权更高的进程进程调度程序就立即停止当前进程(原优先权最高的进程)的执行,重新将处理机分配给新到的优先权最高的进程
  • 这种抢占式的优先权调度算法能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中

三、实时系统

  • 实时系统要求一个请求在一个确定时间内得到响应。分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。

有5个任务,每个任务权重15524,执行时间15534,如何用最短的时间执行完?

  • WARNING:这是我面试中遇到的问题,以下为我个人思考的答案,仅供参考
  • 可以采用多级反馈队列调度算法,可以看成时间片轮转调度和优先级调度的结合
  • 最上面的队列,优先级最高,首先调度优先级高的队列中的进程。若高优先级中队列中已没有调度的进程,则调度次优先级队列中的进程
  • 如果它在一个时间片结束时尚未完成,调度程序便将该进程转入第二队列的末尾,若第二队列的时间片用完后作业还不能完成,一直进入下一级队列,直至完成
  • 在低优先级的队列中的进程在运行时,又有新到达的作业,那么在运行完这个时间片后,CPU马上分配给新到达的作业即抢占式调度CPU

孤儿进程:父进程结束,子进程还没有结束。 没有什么危害会被init回收

僵尸进程:子进程结束了,父进程不知道 会占用进程号,导致没有进程号可用

同步:同步过程有阻塞,线性执行,流程不能跨越。

异步:异步过程当系统接收到返回值或者信息时候,系统会自动触发委托的一步过程,完成一个完整的流程。

堆和栈的区别:

空间分配:栈由操作系统自动分配释放;堆一般由程序员分配释放

申请效率对比:栈使用一级缓存,被调用时通常处于存储空间中,调用后被立即释放;.堆使用二级缓存,生命周期与虚拟机的GC算法有关,调用速度相对较低。

申请大小的限制:栈是向低地址扩展的数据结构,是一块连续的内存的区域;堆是向高地址扩展的数据结构,是不连续的内存区域

死锁

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

死锁出现的原因:

多个进程之间竞争资源

进程之间推进顺序不当

产生死锁的必要条件

1.互斥,有资源只能被一个进程使用

2.请求和保持条件,已经得到进程的资源可以再申请新的资源。

3.不可抢占,已经分配的资源不能被抢占,只能显式释放。

4.循环等待,系统中有两个或者多个的进程组成一条循环,该循环的每个进程都等待着另一个进程占有的资源。

处理策略

1.撤销进程

2.死锁预防:

破坏互斥:不让资源被一个进程独占,可通过假脱机技术允许多个进程同时访问资源;

破坏拥有和请求:1. 已拥有资源的进程不能再去请求其他资源,要求进程在开始执行前请求需要的所有资源;2. 要求进程请求资源时,先暂时释放其当前拥有的所有资源,再尝试一次获取所需的全部资源

破坏不可抢占:有些资源可以通过虚拟化方式实现可抢占

破坏循环等待:1. 保证每个进程在任何时刻只能占用一个资源,如果要请求另一个资源,必须先释放第一个资源;是将所有资源进行统一编号,进程可以在任何时刻请求资源,但要求进程必须按照顺序请求资源

3.死锁检测和避免:银行家算法

4.死锁恢复:从一个或多个进程中抢占资源分配给死锁进程;终止所有的死锁进程

posted @ 2021-04-13 15:42  NodMouse  阅读(128)  评论(0)    收藏  举报