文章目录
1.用户态和内核态的区别
在计算机系统中,通常运行着两类程序:系统程序和应用程序,为了保证系统程序不被应用程序有意或无意地破坏,为计算机设置了两种状态:
- 系统态(也称为管态或核心态),操作系统在系统态运行——运行操作系统程序
- 用户态(也称为目态),应用程序只能在用户态运行——运行用户程序
在实际运行过程中,处理机会在系统态和用户态间切换。相应地,现代多数操作系统将 CPU 的指令集分为特权指令和非特权指令两类。
- 特权指令——在系统态时运行的指令
对内存空间的访问范围基本不受限制,不仅能访问用户存储空间,也能访问系统存储空间,
特权指令只允许操作系统使用,不允许应用程序使用,否则会引起系统混乱。
- 非特权指令——在用户态时运行的指令
一般应用程序所使用的都是非特权指令,它只能完成一般性的操作和任务,不能对系统中的硬件和软件直接进行访问,其对内存的访问范围也局限于用户空间。
UNIX 系统把进程的执行状态分为两种:
1.一种是用户态执行,表示进程正处于用户状态中执行;
2.另一种是核心态执行,表示一个应用进程执行系统调用后,或 I/O 中断、时钟中断后,进程便处于核心态执行。
这两种状态的主要差别在于:
处于用户态执行时,进程所能访问的内存空间和对象受到限制,其所占有的处理机是可被抢占的;
而处于核心态执行中的进程,则能访问所有的内存空间和对象,且所占用的处理机是不允许被抢占的。
用户态切换到内核态的唯一途径——>中断/异常/陷入
内核态切换到用户态的途径——>设置程序状态字
2.死锁
2.1什么是死锁
死锁:一般情况下,如果同一个线程先后两次调用lock,在第一次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此 就永远处于挂起等待状态了,这叫做死锁(Deadlock)。 另一种典型的死锁情形是这样:线程A获 得了锁1,线程B获得了锁2,这时线程A调lock试图获得锁2,结果是需要挂起等待线程B释放 锁2,这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都 永远处于挂起状态了。
2.2 产生死锁的原因?
可归结为如下两点:
a. 竞争资源
系统中的资源可以分为两类:
可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺,CPU和主存均属于可剥夺性资源;
另一类资源是不可剥夺资源,当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。
产生死锁中的竞争资源之一指的是竞争不可剥夺资源(例如:系统中只有一台打印机,可供进程P1使用,假定P1已占用了打印机,若P2继续要求打印机打印将阻塞)
产生死锁中的竞争资源另外一种资源指的是竞争临时资源(临时资源包括硬件中断、信号、消息、缓冲区内的消息等),通常消息通信顺序进行不当,则会产生死锁
b. 进程间推进顺序非法
若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个进程再向前推进,便可能发生死锁
例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2:Request(R1)时,也将因R1已被P1占用而阻塞,于是发生进程死锁
2.3产生的条件:
产生死锁的必要条件:
互斥条件:即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有
不剥夺条件:进程所获得的资源在未使用完毕之前,资源申请者不能强行的从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放
请求和保持条件:进程至少已经占有了一个资源,但又申请了一个新的被其他进程所占有的资源,此时处于等待状态
循环等待条件:若干个进程形成环形链,每个都占用对方申请的下一个资源
2.4解决死锁的基本方法
为使系统不发生死锁,必须设法破坏产生死锁的四个必要条件之一,或者允许死锁产生,但当死锁发生时能检测出思索,并有能力实现恢复。
一般有死锁的预防、死锁避免、死锁的检测与恢复三种方法。
(1) 死锁预防:破坏导致死锁必要条件中的任意一个就可以预防死锁。例如,要求用户申请资源时一次性申请所需要的全部资源,这就破坏了保持和等待条件;将资源分层,得到上一层资源后,才能够申请下一层资源,它破坏了循环等待条件。预防通常会降低系统的效率。
(2) 死锁避免:避免是指进程在每次申请资源时判断这些操作是否安全,例如,使用银行家算法。死锁避免算法的执行会增加系统的开销。
(3) 死锁检测:死锁预防和避免都是事前措施,而死锁的检测则是判断系统是否处于死锁状态,如果是,则执行死锁解除策略。
(4) 死锁解除:这是与死锁检测结合使用的,它使用的方式就是剥夺。即将某进程所拥有的资源强行收回,分配给其他的进程。
死锁预防:
- 打破互斥条件:允许进程同时访问资源(有些资源就是不可以同时访问的,无实用价值)
- 打破不可剥夺条件:比如给进程设置优先级,高优先级的可以抢占资源(实现困难,降低系统性能)
- 打破请求保持条件:实行资源预分配策略,即进程在运行前一次性的向系统申请它所需要的全部资源(不可预测资源的使用,利用率低,降低并发性)
- 破坏循环等待条件:采用这种策略,即把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。所有进程对资源的请求必须严格按资源序号递增的顺序提出(限制和编号实现困难,增加系统开销,有些资源暂时不用也需要先申请,增加了进程对资源的占用时间)
避免死锁:
允许进程动态的申请资源,但系统在进行资源分配前,应先计算此次资源分配的安全性。若此次分配不会导致系统进入不安全状态,则将资源你分配给进程,否则,让进程等待。
所谓安全状态,是指系统能按某种进程推进顺序,为每个进程分配其所需的资源,直至满足每个进程对资源的最大需求,是每个进程都可以顺序的完成。此时成P1P2P3…为安全序列,如果系统无法找到一个安全序列,则称系统处于不安全状态。
并非所有的不安全状态都是死锁状态,但当系统进入不安全状态后,便可能进入死锁状态;反之,只要系统处于安全状态,系统便可以避免进入死锁状态。
银行家算法是最著名的死锁避免算法。
银行家算法:首先需要定义状态和安全状态的概念。系统的状态是当前给进程分配的资源情况。因此,状态包含两个向量Resource(系统中每种资源的总量)和Available(未分配给进程的每种资源的总量)及两个矩阵Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态是指至少有一个资源分配序列不会导致死锁。当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。
检测死锁
首先为每个进程和每个资源指定一个唯一的号码;
然后建立资源分配表和进程等待表。
解除死锁:
当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:
1)资源剥夺法。挂起某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但应防止被挂起的进程长时间得不到资源时,而处于资源匮乏的状态。
2)进程撤销法。强制撤销一个或一部分进程并剥夺这些进程的资源。撤销的原则可以按进程的优先级和撤销进程代价的高低进行。
3)进程回退法。让一个或多个进程回退到足以回避死锁的地步,进程回退时资源释放资源而不是被剥夺。要求系统保持进程的历史信息,设置还原点。
3.调度算法
-
先来先服务(FCFS)调度算法
(1)概念:按照作业/进程进入系统的先后次序进行调度,先进入系统者先调度;即启动等待时间最长的作业/进程。是一种最简单的调度算法,即可用于作业调度,也可用于进程调度

(2) 先来先服务优缺点
1.比较有利于长作业(进程),而不利于短作业(进程)
2.有利于CPU繁忙型作业(进程) ,而不利于I/O繁忙型作业(进程)
3.用于批处理系统,不适于分时系统 -
短作业优先调度算法(SJF)
(1)概念:从队列中选出一个估计运行时间最短的作业优先调度,即可用于作业调度,也可用于进程调度
(2)缺点
1.对长作业不利。严重的是,若一长作业(进程)进入系统的就绪队列,由于调度程序总是优先调度那些(即使是后进来的)短作业(进程),将导致长作业(进程)长期不被调度——饥饿
2.完全未考虑作业(进程)的紧迫程度,因而不能保证紧迫性作业(进程)会被及时处理
3.由于作业(进程)的长短只是根据用户所提供的估计执行时间而定的,而用户又可能会有意或无意地缩短其作业的估计运行时间,致使该算法不一定能真正做到短作业优先调度。
三、高优先权调度算法
即可用于作业调度,也可用于进程调度
-
优先调度算法的类型
(1)非抢占式优先权调度算法
特点:系统一旦把处理机分配给就绪队列中优先权最高的进程后,该进程便一直执行下去,直至完成,或因发生某事件使该进程放弃处理机时,系统才将处理机重新分配给另一优先权最高的进程
主要用于批处理系统中,也可用于某些对实时性要求不严的实时系统中
(2)抢占式优先权调度算法
特点:把处理机分配给优先权最高的进程,但在执行期间,只要出现另一个优先权更高的进程,则进程调度程序就立即停止当前进程的执行,并将处理机分配给新到的优先权最高的进程
注意:只要系统中出现一个新的就绪进程,就进行优先权比较
该调度算法,能更好地满足紧迫作业的要求,故而常用于要求比较严格的实时系统中,以及对性能要求较高的批处理和分时系统中
2、优先权类型
高优先权调度算法,需要比较作业或进程的优先级,所以我们需要了解一下优先级
优先权分为静态优先权、动态优先权
(1)静态优先权
静态优先权在创建进程时确定,且在进程的整个运行期间保持不变。一般地,优先权是利用某一范围内的一个整数来表示的,例如,0∼7或0∼255, 又把该整数称为优先数
确定进程优先权的依据有如下三个方面:
进程类型:系统进程的优先权高于一般用户进程。
进程对资源的需求:如进程的估计执行时间及内存需要量少的进程,应赋予较高的优先权。
用户要求:由用户进程的紧迫程度和用户所付费用的多少来确定优先权。
(2)动态优先权
概念:在创建进程时赋予的优先权是随进程的推进或随其等待时间的增加而改变,以获得更好的调度性能。可规定,在就绪队列中的进程,随其等待时间的增长,其优先权以速率a提高
特征:具有相同优先权初值的进程,则最先进入就绪队列,其将因其动态优先权变得最高而优先获得处理机,此即FCFS算法
具有各不相同的优先权初值的就绪进程,则优先权初值低的进程,在等待了足够的时间后,其优先权便可能升为最高,从而可以获得处理机
注意:当采用抢占式优先权调度算法时,如果再规定当前进程的优先权以速率b下降,则可防止一个长作业长期地垄断处理机 -
高响应比优先调度算法
(1)概念:高响应比优先调度算法既考虑作业的执行时间也考虑作业的等待时间,综合了先来先服务和最短作业优先两种算法的特点。
该算法中的响应比是指作业等待时间与运行比值,响应比公式定义如下:
响应比 =(等待时间+要求服务时间)/ 要求服务时间,即RR=(w+s)/s=1+w/s,因此响应比一定是大于1的。
(2)优缺点
优点:等待时间相同的作业,则要求服务的时间愈短,其优先权愈高,——对短作业有利
要求服务的时间相同的作业,则等待时间愈长,其优先权愈高,——是先来先服务
长作业,优先权随等待时间的增加而提高,其等待时间足够长时,其优先权便可升到很高, 从而也可获得处理机——对长作业有利
是一种折衷,既照顾了短作业,又考虑了作业到达的先后次序,又不会使长作业长期得不到服务。
缺点:要进行响应比计算,增加了系统开销 -
简单的时间片轮转法(RR—Round Robin)
(1)概念:系统将所有的就绪进程按先来先服务的原则排成一个队列,每次调度时,把CPU分配给队首进程,并令其执行一个时间片;当执行的时间片用完时,由一个计时器发出时钟中断请求,调度程序便停止该进程的执行,并将其放就绪队列尾;然后,再把处理机分配给就绪队列中新的队首;时间片的大小从几ms到几百ms
(2)缺点:紧迫任务响应慢。
UNIX中采用:时间片+优先权
(3)时间片选取
太小,会频繁发生中断、进程上下文切换,增加系统开销,但利于短作业
太大,退化成FCFS
——时间片应该略大于一次典型交互的时间
4.页面置换算法
页面置换算法的功能:当出现缺页异常,需调入新页面而内存已满时,置换算法选择被置换的物理页面。
页面置换算法的设计目标:尽可能减少页面的调入调出次数,把未来不再访问或短期内不访问的页面调出。
-
先进先出算法(First-In First-Out, FIFO)
思路:选择在内存驻留时间最长的页面进行置换
实现:维护一个记录所有位于内存中的逻辑页面链表,链表元素按驻留内存的时间排序,链首最长,链尾最短,出现缺页时,选择链首页面进行置换,新页面加到链尾
特点:实现简单;性能较差,调出的页面可能是经常访问的
-
最近最久未使用算法 (Least Recently Used, LRU)
思路:选择最长时间没有被引用的页面进行置换,因为如果某些页面长时间未被访问,则它们在将来还可能会长时间不会访问
实现:缺页时,计算内存中每个逻辑页面的上一次访问时间,选择上一次使用到当前时间最长的页面
特点:可能达到最优的效果,维护这样的访问链表开销比较大
-
最不常用算法(Least Frequently Used, LFU)
思路:缺页时,置换访问次数最少的页面
实现:每个页面设置一个访问计数,访问页面时,访问计数加1,缺页时,置换计数最小的页面
特点:算法开销大,开始时频繁使用,但以后不使用的页面很难置换
-
时钟置换算法(Clock)
思路:仅对页面的访问情况进行大致统计
实现:在页表项中增加访问位,描述页面在过去一段时间的内访问情况,将各页面组织成环形链表,指针指向最先调入的页面,访问页面时,在页表项记录页面访问情况,缺页时,从指针处开始顺序查找未被访问的页面进行置换
特点:时钟算法是LRU和FIFO的折中
5.select、poll、epoll之间的区别
select和poll差不多,poll采用pollfd来作为文件描述符集,代替了fd_set;这两者都有的缺点:每次调用都需要拷贝一次fd_set(或pollfd),在描述符数量大时开销较大。内核需要遍历传入的fd_set,效率较低。而epoll主要通过epoll_ctl使每次注册新事件时拷贝一次所有的fd;epoll_wait只需要轮询一个就绪队列是否是空,这是因为epoll采用了回调机制,将就绪的fd插入到就绪队列中,因此不像select和poll中,需要轮询一个fd_set(很耗cpu)。
“epoll模式在操作中获得就绪的文件描述符时,返回的不是实际的文件描述符,而是一个代表就绪文件描述符的值,然后在文件描述符数组中查询对应的的文件描述符。这样避免系统调用时候在内存中数据结构复制的开销。“
select、poll、epoll之间的区别参考
批处理中的调度
-
先来先服务
按照请求顺序为进程分配 CPU。最基本的,会有一个就绪进程的等待队列。当第一个任务从外部进入系统时,将会立即启动并允许运行任意长的时间。它不会因为运行时间太长而中断。当其他作业进入时,它们排到就绪队列尾部。当正在运行的进程阻塞,处于等待队列的第一个进程就开始运行。当一个阻塞的进程重新处于就绪态时,它会像一个新到达的任务,会排在队列的末尾,即排在所有进程最后。 -
最短作业优先
当输入队列中有若干个同等重要的作业被启动时,调度程序应使用最短优先作业算法需要注意的是,在所有的进程都可以运行的情况下,最短作业优先的算法才是最优的。
-
最短剩余时间优先
最短作业优先的抢占式版本被称作为 最短剩余时间优先(Shortest Remaining Time Next) 算法。使用这个算法,调度程序总是选择剩余运行时间最短的那个进程运行。当一个新作业到达时,其整个时间同当前进程的剩余时间做比较。如果新的进程比当前运行进程需要更少的时间,当前进程就被挂起,而运行新的进程。这种方式能够使短期作业获得良好的服务。
交互式系统中的调度
- 轮询调度
每个进程都会被分配一个时间段,称为时间片(quantum),在这个时间片内允许进程运行。如果时间片结束时进程还在运行的话,则抢占一个 CPU 并将其分配给另一个进程。如果进程在时间片结束前阻塞或结束,则 CPU 立即进行切换。轮询算法比较容易实现。调度程序所做的就是维护一个可运行进程的列表,当一个进程用完时间片后就被移到队列的末尾。
将时间片时间设置得太短会导致过多的进程切换并降低 CPU 效率,但设置时间太长会导致一个短请求很长时间得不到响应。最好的切换时间是在 20 - 50 毫秒之间设置。
-
优先级调度
每个进程都被赋予一个优先级,优先级高的进程优先运行。
但是也不意味着高优先级的进程能够永远一直运行下去,调度程序会在每个时钟中断期间降低当前运行进程的优先级。如果此操作导致其优先级降低到下一个最高进程的优先级以下,则会发生进程切换。或者,可以为每个进程分配允许运行的最大时间间隔。当时间间隔用完后,下一个高优先级的进程会得到运行的机会。 -
最短进程优先
最短作业优先常常伴随着最短响应时间,优先运行最短响应时间的进程。
最短的进程选择方法:
根据进程过去的行为进行推测,并执行估计运行时间最短的那一个。假设每个终端上每条命令的预估运行时间为 T0,现在假设测量到其下一次运行时间为 T1,可以用两个值的加权来改进估计时间,即aT0+ (1- a)T1。通过选择 a 的值,可以决定是尽快忘掉老的运行时间,还是在一段长时间内始终记住它们。这种通过当前测量值和先前估计值进行加权平均从而得到下一个估计值的技术称作 老化(aging)。这种方法会使用很多预测值基于当前值的情况。 -
保证调度
在一个有 n 个进程运行的单用户系统中,若所有的进程都等价,则每个进程将获得 1/n 的 CPU 时间。 -
彩票调度
为进程提供各种系统资源(例如 CPU 时间)的彩票。当做出一个调度决策的时候,就随机抽出一张彩票,拥有彩票的进程将获得该资源。在应用到 CPU 调度时,系统可以每秒持有 50 次抽奖,每个中奖者将获得比如 20 毫秒的 CPU 时间作为奖励。
实时系统中的调度
实时系统可以分为两类,硬实时(hard real time) 和 软实时(soft real time) 系统,硬实时必须要满足绝对的截止时间; 软实时是虽然不希望偶尔错失截止时间,但是可以容忍。在这两种情形中,实时都是通过把程序划分为一组进程而实现的,其中每个进程的行为是可预测和提前可知的。这些进程一般寿命较短,并且极快的运行完成。在检测到一个外部信号时,调度程序的任务就是按照满足所有截止时间的要求调度进程。
实时系统中的事件可以按照响应方式进一步分类为周期性(以规则的时间间隔发生)事件或 非周期性(发生时间不可预知)事件。一个系统可能要响应多个周期性事件流,根据每个事件处理所需的时间,可能甚至无法处理所有事件。例如,如果有 m 个周期事件,事件 i 以周期 Pi 发生,并需要 Ci 秒 CPU 时间处理一个事件,那么可以处理负载的条件是
只有满足这个条件的实时系统称为可调度的,这意味着它实际上能够被实现。一个不满足此检验标准的进程不能被调度,因为这些进程共同需要的 CPU 时间总和大于 CPU 能提供的时间。
时调度算法
-
最早截止时间优先EDF
根据任务的最迟开始时间确定优先级,该时间越早优先级越高,系统中保持一个实时任务优先级就绪队列,调度程序选择队首任务分配CPU,可采取抢占式和非抢占式调度。 -
最低松弛度优先-优先级调度的一种(LLF算法)
根据任务紧急(或松弛)的程序来确定任务的优先级,任务的紧急程度越高,为该任务所赋予的优先级就越高,以使之优先执行。系统中保持一个实时任务优先级就绪队列,调度程序选择队首任务分配CPU。
实时调度算法的分类:
按任务性质分类:硬实时调度算法、软实时调度算法
按调度方式分类:非抢占式调度、抢占式调度
按调度时间分类:静态调度算法、动态调度算法
抢占式和非抢占式调度算法
所谓非抢占式就是等待当前任务完成再执行需要运行的程序。
抢占式算法
所谓抢占式即使当前任务没有完成,我也要将当前任务强行终止来执行需要调度的程序。比如轮转调度中时间片抢占。
静态调度和非静态调度
静态在系统开始运行之前做出调度决策;非静态调度在运行过程中进行调度决策。只有在可以提前掌握所完成的工作以及必须满足的截止时间等信息时,静态调度才能工作,而动态调度不需要这些限制。