常用的调度算法(包含实例)|操作系统


1.先来先服务调度算法(FCFS)

原理: {\color{Violet}原理:} 原理:

∙ \bullet 先来先服务(First-Come-First-served)调度算法是最简单非抢占的调度算法。

∙ \bullet 它通过管理一个FIFO就绪队列来实现,从前到后按顺序将CPU分配给进程。

举例: {\color{Violet}举例:} 举例:

∙ \bullet 现在有如下一组进程:

进程执行时间
P130
P25
P32

所以执行顺序为 < P 1 、 P 2 、 P 3 > <P_{1}、P_{2}、P_{3}> <P1P2P3> ,我们画出它的甘特图来形象的理解:
在这里插入图片描述
下面的时刻表示该进程占用CPU的执行时间。(后面的几种调度方法也使用甘特图来帮助理解。)

所以可以计算求得三个进程的平均等待时间为:
0 + 30 + 35 3 ≈ 21.7 {\color{Red}\frac{0+30+35}{3}≈21.7} 30+30+3521.7

特点: {\color{Violet}特点:} 特点:

∙ \bullet FCFS调度算法对短进程不利,尤其当一个短进程跟在长进程后面时,它需要等待很长的时间。有时候会导致CPU和设备的利用率很低,在实际情况中,FCFS算法通常与其他算法结合使用。


2.优先级调度算法

原理: {\color{Violet}原理:} 原理:

∙ \bullet 由用户或者系统按照某种原则给进程一个优先级,系统总是调度优先级最高的那个进程运行。

∙ \bullet 优先级可以分为静态优先级动态优先级。静态优先级就是指优先级确定以后就不再改变,比如说按照它们的执行时间长短来确定等等;动态优先级会随着进程的不断执行而发生改变,比如说可以按照等待时间的长短划分优先级等等。

∙ \bullet 对优先级动态调整可以改善系统性能,但是动态优先级调度算法会增加系统开销。

举例: {\color{Violet}举例:} 举例:

∙ \bullet 现在有如下一组进程(采用静态优先级调度算法):

进程执行时间优先级
P195
P241
P323
P414

所以执行顺序为 < P 2 、 P 3 、 P 4 、 P 1 > <P_{2}、P_{3}、P_{4}、P_{1}> <P2P3P4P1>,我们画出它的甘特图如下:

在这里插入图片描述
所以可以计算求得四个进程的平均等待时间为:
0 + 4 + 6 + 7 4 = 4.25 {\color{Red}\frac{0+4+6+7}{4}=4.25} 40+4+6+7=4.25

特点: {\color{Violet}特点:} 特点:

∙ \bullet 可能会出现“饥饿”现象,就是优先级低的进程会一直等待CPU,未来避免这种问题的出现,我们可以采用“老化”的策略,就是按一定时间间隔提高等待进程的的优先级数值。

∙ \bullet 我们假设它们几乎同时到达,但是实际情况中总会有先后顺序,在支持抢占的系统中,当新进程进入就绪队列时,如果它的优先级高于当前运行进程的优先级,那么就会抢占CPU;在非抢占系统中,只是将新进程加入了就绪队列中。


3.最短作业优先调度算法(SJF)

原理: {\color{Violet}原理:} 原理:

∙ \bullet 最短作业优先(Shortest-Job First)调度算法克服了FCFS的对短进程不利的缺点,它在就绪队列中选择处理时间最短的进程,如果时间相同则可以按照FCFS准则来处理。

∙ \bullet 它提高了系统的吞吐量,但是反过来又对长进程不利。

∙ \bullet 它分为抢占式和非抢占式两种情况

举例: {\color{Violet}举例:} 举例:

∙ \bullet 现在有如下一组进程,假设它们同时到达(非抢占式):

进程执行时间
P15
P24
P39
P43

所以执行顺序为 < P 4 、 P 2 、 P 1 、 P 3 > <P_{4}、P_{2}、P_{1}、P_{3}> <P4P2P1P3>,我们画出它的甘特图如下:
在这里插入图片描述
所以可以计算求得三个进程的平均等待时间为:
0 + 3 + 7 + 12 4 = 5.5 {\color{Red}\frac{0+3+7+12}{4}=5.5} 40+3+7+12=5.5

∙ \bullet 现在有如下一组进程,假设它们不同时到达(抢占式):

进程到达时间执行时间
P108
P214
P329
P435

最初只有P1进程,那么执行P1进程;当时间1时P2到达,此时P1剩余执行时间为7,P2执行时间为4,那么执行P2进程;当时间2时,P3到达,此时最短执行时间仍然为P2;时间3时,P4到达,此时P2执行时间为2,P4也为2,所以先让P2执行完在让P4执行,然后再让P1执行,最后在让P3执行。

所以执行顺序为 KaTeX parse error: Expected 'EOF', got '}' at position 31: …{4}、P_{1}、P_{3}}̲>,我们画出它的甘特图如下:

在这里插入图片描述
所以可以计算求得三个进程的平均等待时间为:
( ( 10 − 1 ) + 0 + ( 17 − 2 ) + ( 5 − 3 ) ) 4 = 6.5 {\color{Red}\frac{((10-1)+0+(17-2)+(5-3))}{4}=6.5} 4((101)+0+(172)+(53))=6.5

分母上面的式子为每个进程开始执行的时间减去开始等待的时间之和。

特点: {\color{Violet}特点:} 特点:

∙ \bullet 对于非抢占的SJF调度算法,可以看作是优先级调度算法的一种特例。


4.最高响应比优先调度算法(HRRN)

原理: {\color{Violet}原理:} 原理:

∙ \bullet 最高响应比(Highest Response Ratio Next)调度算法集合了FCFS算法和非抢占SJF算法的优点,使用响应比R来表征,即:
R = W + S S   ( W 为等待时间、 S 为预计执行时间 ) R = \frac{W+S}{S} \ (W为等待时间、S为预计执行时间) R=SW+S (W为等待时间、S为预计执行时间)

∙ \bullet 在该算法下,等待时间相同的时候短进程响应比高于长进程,短进程优先被调度;而随着等待时间增长,进程的响应比增加,长进程被调度的可能性也会增加。

举例: {\color{Violet}举例:} 举例:

∙ \bullet 现在有如下一组进程如下:

进程到达时间执行时间
P1010
P211
P322
P431
P545

∙ \bullet 0时刻P1运行,10时刻P1运行完毕,此时P2 ~ P5的响应比为:

P 2 : 1 + 9 1 = 10 ;     P 3 : 2 + 8 2 = 5 ; P_{2}:\frac{1+9}{1}=10 ;\ \ \ P_{3}:\frac{2+8}{2}=5; P2:11+9=10;   P3:22+8=5;

P 3 : 1 + 7 1 = 8 ;     P 4 : 5 + 6 2 = 5.5 ; P_{3}:\frac{1+7}{1}=8 ;\ \ \ P_{4}:\frac{5+6}{2}=5.5; P3:11+7=8;   P4:25+6=5.5;

∙ \bullet 所以P2运行,直到11时刻运行结束,此时P3 ~ P5的响应比为:

P 3 : 2 + 9 2 = 5.5 ;     P 4 : 1 + 8 2 = 9 ;     P 5 : 5 + 7 5 = 2.4 ; P_{3}:\frac{2+9}{2}=5.5 ;\ \ \ P_{4}:\frac{1+8}{2}=9; \ \ \ P_{5}:\frac{5+7}{5}=2.4; P3:22+9=5.5;   P4:21+8=9;   P5:55+7=2.4;

∙ \bullet 所以P4运行,直到12时刻运行结束,此时P3 和 P5的响应比为:

P 3 : 2 + 10 2 = 6 ;     P 5 : 5 + 8 5 = 2.6 ; P_{3}:\frac{2+10}{2}=6 ;\ \ \ P_{5}:\frac{5+8}{5}=2.6; P3:22+10=6;   P5:55+8=2.6;

∙ \bullet 所以先执行P3,后执行P5

∙ \bullet 所以执行顺序为 KaTeX parse error: Expected 'EOF', got '}' at position 31: …{4}、P_{3}、P_{5}}̲>,我们画出它的甘特图如下:

在这里插入图片描述
所以可以计算求得五个进程的平均等待时间为:
( 0 + ( 10 − 1 ) + ( 11 − 2 ) + ( 12 − 3 ) + ( 14 − 4 ) ) 5 = 7.4 {\color{Red}\frac{(0+(10-1)+(11-2)+(12-3)+(14-4))}{5}=7.4} 5(0+(101)+(112)+(123)+(144))=7.4


5.轮转调度算法(RR)

原理: {\color{Violet}原理:} 原理:

∙ \bullet 轮转(Round Robin)调度算法是一种基于抢占的调度策略,在分时系统中,每个进程会被分配一个固定的时间片,就绪队列中的进程按顺序依此调度运行。

∙ \bullet 时间片过短会使进程切换过于频繁,增加系统开销;时间片过长会使进程响应时间增加。

举例: {\color{Violet}举例:} 举例:

∙ \bullet 现在有如下一组进程如下:

进程执行时间
P124
P23
P33

这里时间片我们选择为4,按照原理可得甘特图如下:
在这里插入图片描述
所以可以计算求得三个进程的平均等待时间为:
6 + 4 + 7 3 ≈ 5.67 {\color{Red}\frac{6+4+7}{3}≈5.67} 36+4+75.67


6.多级反馈轮转调度算法

原理: {\color{Violet}原理:} 原理:

∙ \bullet 是对简单轮转调度算法的改进,它把新就绪的进程和被抢占后回到就绪队列的进程加以区分,将它们放入不同优先级的就绪队列中;

∙ \bullet 被抢占后放回就绪队列的进程优先级会降低,但是运行的时间片长度会增加。


7.实时系统的调度算法

原理: {\color{Violet}原理:} 原理:

∙ \bullet 在实时系统中会给出一个最后期限,最后期限指定任务开始或结束的时间,任务必须严格按照最后期限执行。

  • 33
    点赞
  • 146
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
### 回答1: PID算法是一种常用的控制算法,用于实现系统的稳定控制。它采用比例(P)、积分(I)和微分(D)三个部分来调节控制器的输出。下面我来对PID算法的资料进行汇总,并附上一个简单的PID控制器实例源代码。 首先,PID算法的资料可以分为理论资料和应用实例。理论资料主要包括PID算法的原理、公式推导、参数调整方法等内容,可以从控制理论书籍、学术论文和网络资源中获取。应用实例则是指针对不同系统的PID控制器的具体应用案例和实现代码,可以从控制工程实践书籍、控制论坛和开源项目中找到。 对于PID算法实例源代码,这里给出一个简单的示例供参考: ```python # PID控制器实例代码 class PIDController: def __init__(self, Kp, Ki, Kd): self.Kp = Kp self.Ki = Ki self.Kd = Kd self.previous_error = 0 self.integral = 0 def control(self, setpoint, process_variable): error = setpoint - process_variable self.integral += error derivative = error - self.previous_error output = self.Kp * error + self.Ki * self.integral + self.Kd * derivative self.previous_error = error return output # 使用PID控制器进行控制 pid_controller = PIDController(Kp=1.0, Ki=0.5, Kd=0.2) setpoint = 50.0 # 设定值 process_variable = 0.0 # 过程变量 for _ in range(100): control_signal = pid_controller.control(setpoint, process_variable) process_variable += control_signal print(process_variable) ``` 这段代码定义了一个PID控制器类,包括构造方法和控制方法。在示例中,我们设定了一个目标值setpoint和初始过程变量process_variable,然后循环执行控制方法,计算得到控制信号并更新过程变量,最终输出结果。 综上所述,PID算法的资料汇总包括理论资料和应用实例。PID控制器实例源代码可以根据具体需求进行调整和优化,提高系统的控制性能。 ### 回答2: pid算法是一种操作系统中用于进程调度的算法。其全称为进程标识符(Process Identifier)算法,通过给每个进程分配一个唯一的标识符来管理和调度进程,以保证操作系统能够正确地管理和运行多个进程。 pid算法的基本原理是在每个进程创建时,为其分配一个唯一的进程标识符。这个标识符是一个非负整数,通常从0开始递增分配。当一个进程终止时,其进程标识符将被回收,可以用于分配给新创建的进程。这样,通过唯一的进程标识符,操作系统可以针对不同的进程进行管理和调度。 pid算法的实现通常包括两个主要步骤:进程创建和进程终止。进程创建时,操作系统会分配一个可用的标识符给新进程,并为其分配资源。进程终止时,操作系统会回收进程所占用的资源,并将其进程标识符标记为可用状态,以供下次分配给新进程使用。 下面是一个简单的pid算法的实例源代码: ```c++ #include <iostream> #include <vector> class Process { public: Process(int id) : pid(id) {} int getPID() const { return pid; } private: int pid; }; class PIDManager { public: int allocate() { int pid = getNextAvailablePID(); if(pid != -1) { pids[pid] = true; return pid; } return -1; // 如果没有可用的pid } void deallocate(int pid) { if(pid >= 0 && pid < pids.size()) { pids[pid] = false; } // 释放资源等操作 } private: int getNextAvailablePID() { for(int i = 0; i < pids.size(); ++i) { if(!pids[i]) { return i; } } return -1; } std::vector<bool> pids = std::vector<bool>(1000, false); // 假设操作系统最多支持1000个进程 }; int main() { PIDManager manager; int pid1 = manager.allocate(); int pid2 = manager.allocate(); std::cout << "PID1: " << pid1 << std::endl; std::cout << "PID2: " << pid2 << std::endl; manager.deallocate(pid1); manager.deallocate(pid2); return 0; } ``` 这段示例代码演示了一个简单的pid算法的实现。PIDManager类负责管理pid的分配和回收,allocate函数尝试分配一个可用的pid,deallocate函数用于回收不再使用的pid。在主函数中,我们可以看到该算法的使用流程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

比奇堡咻飞兜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值