您的位置:首页 > 其它

操作系统相关资料之二

2016-03-05 15:22 176 查看
CPU调度

CPU的成功调度依赖用户如下的属性:进程执行由CPU执行和I/O等待周期组成,进程就在这两个状态之间切换。

当CPU空闲时,操作系统就必须从就绪队列中选择一个进程来执行。进程选择由短期调度程序/CPU调度程序来执行。调度程序从内存中选择一个可执行的进程,并为之分配CPU资源。

抢占调度

CPU的调度策略可能发生在如下四种情况:

1、进程从运行状态切换到等待状态(如L/O请求,调用wait()等待一个字进程终止)2、进程从运行状态切换到就绪状态(如中断发生)3、进程从等待状态切换到就绪状态(如L/O完成)4、进程终止

当调度方案只能发生在1和4两种情况是,称调度方案是非抢占的或协作的。否则,调度方案是抢占的。采用非抢占调度,CPU一旦分配给一个进程,那么该进程就会一直占有CPU直到进程终止或切换到等待状态。

抢占式。现行进程在运行过程中,如果有重要或紧迫的进程到达(其状态必须为就绪),则现运行进程将被迫放弃CPU,系统将CPU立刻分配给新到达的进程。

调度算法(这些都是单CPU内的调度算法)
1、先到先服务调度(FCFS---first come first serve),采用这种方案,先请求CPU的进程先分配到CPU。FCFS调度算法是非抢占的,一旦CPU被分配给一个进程,该进程就会保持CPU直到释放CPU为止,即程序终止或请求I/O。
2、最短作业优先调度(SJF),这种算法将每个进程与其下一个CPU区间段相关联。当CPU空闲时,它会赋给具有最短CPU区间的进程,如果两个进程具有相同长度,那么可以使用FCFS调度来处理,SJF算法可能是抢占或非抢占的。CPU区间段越短,进程的优先级越高。
3、优先级调度,SJF算法可以作为通用优先级调度算法的一个特例,每个进程都有一个优先级与其关联,具有最高优先级的进程会分配到CPU。具有相同优先级的进程按照FCFS书序调度。优先级调度算法的一个主要问题是无穷阻塞或饥饿。
4、轮转法调度(RR,round-robin)调度算法是专门为分时系统设计的,类似于FCFS算法,但是增加了抢占以切换进程。为每个进程分配不超过一个时间片的CPU资源。如果进程的CPU区间超过一个时间片(操作系统中每个时间片大小一定),那么该进程会被抢占,而被放回到就绪队列。RR调度算法那是可抢占的,

RR算法性能很大程度上依赖于时间片的大小。尽管时间片应该比上下文切换时间长,但是也不能太大。如果时间片太大,那么RR调度就演变成了FCFS调度。根据经验,百分之八十的CPU区间应该小于时间片。
5、多级队列调度,将就绪队列分成多个独立队列,根据进程的属性,如内存大小、进程优先级、进程类型,一个进程被永久的分配到一个队列。每个队列有自己的调度算法。
6、多级反馈队列调度,通常在使用多级队列调度算法时,进程进入系统时被永久分配到一个队列。与子相反,多级反馈调度算法允许进程在队列之间移动。主要思想是根据不同CPU区间的特点以区分进程,如果进程使用过多的CPU时间,那么会被转移到更低优先级队列。这种方案将I/O约束和交互进程留在更高优先级队列。此外,在较低优先级队列中等待时间过长的进程会被转移到更高优先级队列,这种形式的老化阻止饥饿的发生。

多处理器调度

多处理器的调度方法
在一个多处理器中,CPU调度的一种方法是让一个处理器(主服务器)处理所有的调度决定、I/O处理以及其他系统果冻,其他的处理器只执行用户代码,这样的调度算法是非对称多处理方法(AMP)。这种方法是只有一个处理器访问系统数据结构,减轻了数据共享的需要。

 

另一种方法是SMP(对称多处理),即每个处理器自我调度。所有进程可能处于一个共同的就绪队列中,或是每个处理器都有自己的私有就绪队列。无论如何,调度通过每个处理器检查共同就绪队列并选择一个进程来执行。

处理器亲和力

在处理器上,对于使缓存无效/重新构建的代价相当高,所以绝大多数的SMP系统师徒避免将进程从一个处理器移至另一个处理器,而是使一个进程在同一个处理器上运行,这被称为处理器亲和力,即一个进程需由一种对其运行所在处理器的亲和力。

当一个操作系统具有设法让一个进程保持在同一个处理器上运行的策略,但是不能做任何保证时,则会出现软亲和性(soft affinity)。此时,进程可能在处理器之间移动。有的系统,如Linux,还提供一个支持硬亲和性(hardaffinity)的系统调用,从而允许进程指定它不允许移至其他处理器。

负载平衡

在SMP系统中,保持所有处理器的工作平衡,以完全利用多处理器的优点。否则,将产生一个或者多个处理器空闲,而其他处理器处于高工作负载状态,并有一系列进程在等待CPU。通常情况下,负载平衡只是对那些拥有自己私有的可执行进程的处理器而言是必要的(亦即具有私有就绪队列)。在具有共同队列的系统中,通常不需要负载平衡。

Linix操作系统下并不区分线程和进程,在讨论Linux调度程序时使用术语任务(task),其他操作系统应该会区分进程和线程。

Linux调度

现有的Linux调度程序提供了对SMP的支持,包括处理器亲和性和负载平衡,以及提供了公平及时交互式任务的支持。Linux调度程序时抢占的、基于优先级的算法,具有两个独立的优先级范围:从0~99的real-time(实时任务)范围和从100~140的nice(其他任务)范围。这两个范围映射到全局优先级,其中数值越低表示优先级越高。Linux给较高的优先级分配较长的时间片,给较低的优先级分配较短的时间片。其中,实时任务被分配静态优先级,所有其他任务被分配具有动态优先级。

由于对SMP的支持,每个处理器维护它们自己的运行队列,并独立的调度它自己。每个运行队列包括两个优先级队列---活动的(时间片没用完)和到期的(时间片耗尽)。每个处理器从自己的运行队列中调度任务优先级高的任务来执行,当所有任务都耗尽其时间片(即活动队列为空)时,两个优先级队列相互交换,到期队列变成活动队列,反之亦然。

当任务耗尽其时间片并移至到期队列后,需要重新计算动态优先级。因此,当两个队列交换后,新的活动队列中的所有任务被分配以新的优先级及相应的时间片。

进程同步

相互协作的进程可以直接共享逻辑地址空间(即代码和数据),或者只能通过文件或消息来共享数据。共享数据的并发访问可能产生数据的不一致。所以需要确保共享同一逻辑地址空间的协作进程可有序的执行,从而能维护数据的一致性。

临界问题

每个进程都有一个代码段称为临界区,在该区中进程可能改变共同变量、更新一个表、写一个文件等。这种系统的重要特征是当一个进程进入临界区,没有其他进程可被允许在临界区内执行,即没有两个进程可同时在临界区内执行。临界区问题是设计一个以便进程协作的协议。每个进程必须请求进入临界区,实现这一请求的代码段称为进入区,临界区之后可以有退出区,其他代码是剩余区。

临界区问题的解答必须满足如下三项要求:

互斥:只能有一个进程在临界区内执行。前进:确定下一个进入临界区的是谁,但是不能无限等待 有限等待:其他进程进入允许进入临界区的次数是有上限的

有两种方法用于处理操作系统内的临界问题:抢占内核与抢占内核。抢占内核允许处于内核模式的进程被抢占,费抢占内核不允许处于内核模式的进程被抢占。显然,对于非抢占内核不会出现竞争条件,因为同一时刻只有一个进程在内核中运行,知道该进程退出内核模式、阻塞或自动退出CPU控制。对于SMP结构,抢占内核更难设计,因为两个处于内核模式的进程可同时运行在不同的处理器上。

抢占内核比非抢占内核更适合实时编程,因为它能允许实时进程抢占处于内核模式运行的进程。再者,前之感内核的响应更快,因为处于内核模式的进程释放CPU之前不会运行太久。

Linux2.6之后的版本都是抢占式的内核。

一般说来,可以说任何临界区问题都需要一个简单的工------锁。通过要求临界区用所来保护,就可以避免竞争条件,即一个进程进入临界区之间必须得到锁,而在其退出临界区时释放该锁。

信号量(semaphore)及其用法

信号量S是一个整型变量,除了初始化之外,它只能通过两个标准原子操作:wait()和signal()来访问。在wait()和signal()操作中,对信号量整形值的修改必须是不可分的执行,即当一个进程修改信号量值时,不能有其他进程同时修改同一信号量的值。

信号量的主要缺点是忙等待,当一个进程位于其临界区内,任何试图进入临界区的进程都必须在其代码中连续循环以等待信号量条件满足。忙等待浪费了CPU时钟,这种类型的信号量也称为自旋锁,这是因为进程在其等待锁时还在运行(自旋锁有其有点,进程在等待锁时不进行上下文切换,而上下文切换可能需要花费相当长的时间。因此,如果锁占用时间短,那么自旋锁是有用的。自旋锁常用语多核处理器中,这样一个线程在一个处理器自旋时,另一线程可在另一处理器上在其临界区内执行)。

阻塞操作是将一个进程放入到与信号量相关的等待队列中,并将该进程切换到等待状态。接着,控制权转到CPU调度程序,以选择另一个进程来执行。一个阻塞在等待信号量上的进程,可以再其他进程执行signal()操作之后被重新执行。该进程的重新执行是通过wakeup()操作来执行的,该操作将进程从等待状态切换到就绪状态。接着,该进程被放入到就绪队列中。

每个信号量是一个结构体,每个信号量都有一个整形值和一个进程链表。当一个进程必须等待信号量,就加入到进程链表上。操作signal()会从等待进程链表中取一个进程以唤醒。

死锁和饥饿

具有等待队列的信号量的实现可能导致这样的情况:两个或多个进程无线的等待一个时间,而该时间只能由这些进程之一来产生。这里的时间是signal()操作执行。当出现这样的状态时,这些进程被称为死锁。

示例:假如系统由两个进程组成---P0和P1,每个都访问共享信号量Q和S

 



wait(S)的执行必须等待signal(s)完成才能执行。这样P0和P1两个进程就一直执行不到,一直处在等待状态,那么P0和P1就死锁了。

与死锁相关的另一个问题是无限期阻塞或饥饿,即进程在信号量内无限期等待。

哲学家进餐问题

五个哲学家五根筷子,一张圆桌,一盆米饭,每个哲学家只能拿起邻座的筷子才能吃饭。

哲学家进餐问题是一个典型的同步问题,这是一个并发控制问题的例子。它是需要在多个进程之间分配多个资源且不会出现死锁和饥饿的典型例子。

一种简单的方法是每根筷子都用一个信号量表示,一个哲学家通过执行wait()操作试图获取相应的筷子,他通过signal()操作释放相应的筷子。这样虽然能保证没有两个哲学家同时使用一根筷子,但是这回导致死锁。

使用信号量解决临界问题:所有进程共享一个信号量变量mutex,其初始化为1.每个进程在进入临界区之前执行wait(mutex),之后执行signal(mutex)。如果不遵守这样的顺序,那么这两个进程会同时出现在临界区里面。

有的时候信号量使用不正确解决临界问题的时候会很容易产生各种类型的错误。现在提供一种管程结构来解决这样的问题,同时需要同步机制由condition来表示。对condition结构体的操作仅有wait()和signal()。

进程和线程中互斥锁和信号量的区别(百度之)

多个进程可能竞争一定数量的资源,某个进程申请资源,如果这时资源不可用,那么该进程进入等待状态。若果所申请的资源被其他进程占有,那么该等待进程有可能再也无法改变其状态。这种情况称为死锁。

进程或线程多资源的使用正常的顺序是:申请—使用---释放。

资源的申请与释放为系统调用可使用:request()/release()(设备)、open()/close()(收文件)、allocate()/free()(内存)。其他资源的申请与释放可以通不过信号量的wait()和signal()操作或互斥锁的获取与释放来完成。

当一组进程中的每个进程都在等待一个时间,而这个时间只能由这组进程的另一进程引起,那么这组进程就处于死锁状态。

死锁出现的四个必要条件:互斥、占有并等待、非抢占、循环等待,至少确保其中一项不发生,死锁就能避免。

死锁避免算法动态的检测资源分配状态以确保循环等待条件不可能成立。资源分配状态是由可用资源和已分配资源,以及进程最大需求所决定的。

避免死锁的两种算法:银行家算法和资源分配图算法

死锁恢复的方法:进程终止、资源抢占。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 









 



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: