此博客处内容为 《操作系统导论》(Operating Systems: Three Easy Pieces)第8章(调度:多级反馈队列) 作业习题程序说明。
原书英文版地址 https://pages.cs.wisc.edu/~remzi/OSTEP/
第7章 作业习题程序说明链接:https://blog.csdn.net/cai1149735196/article/details/115208047
在程序mlfq.py中,让你了解本章的多级反馈队列(Multi-level Feedback Queue, MLFQ)是如何工作的。其工作方式类似第7章程序,若要了解详细的运行方式,请使用以下代码:
# 在命令行输入如下命令
>> python mlfq.py
# 得到如下输出结果
Use the help flag (-h) to see the options:
Usage: mlfq.py [options]
Options:
-h, --help show this help message and exit
-s SEED, --seed=SEED the random seed
-n NUMQUEUES, --numQueues=NUMQUEUES
number of queues in MLFQ (if not using -Q)
-q QUANTUM, --quantum=QUANTUM
length of time slice (if not using -Q)
-Q QUANTUMLIST, --quantumList=QUANTUMLIST
length of time slice per queue level,
specified as x,y,z,... where x is the
quantum length for the highest-priority
queue, y the next highest, and so forth
-j NUMJOBS, --numJobs=NUMJOBS
number of jobs in the system
-m MAXLEN, --maxlen=MAXLEN
max run-time of a job (if random)
-M MAXIO, --maxio=MAXIO
max I/O frequency of a job (if random)
-B BOOST, --boost=BOOST
how often to boost the priority of all
jobs back to high priority (0 means never)
-i IOTIME, --iotime=IOTIME
how long an I/O should last (fixed constant)
-S, --stay reset and stay at same priority level
when issuing I/O
-l JLIST, --jlist=JLIST
a comma-separated list of jobs to run,
in the form x1,y1,z1:x2,y2,z2:... where
x is start time, y is run time, and z
is how often the job issues an I/O request
-c compute answers for me
使用模拟器有几种不同的方法。一种方法是生成一些随机的作业,看看是否能够找出它们在MLFQ调度器下的行为。例如,如果希望创建随机生成的三个作业的工作负载,只需键入
>> python mlfq.py -j 3
然后你会看到具体的定义如下
Here is the list of inputs:
OPTIONS jobs 3
OPTIONS queues 3
OPTIONS quantum length for queue 2 is 10
OPTIONS quantum length for queue 1 is 10
OPTIONS quantum length for queue 0 is 10
OPTIONS boost 0
OPTIONS ioTime 0
OPTIONS stayAfterIO False
For each job, three defining characteristics are given:
startTime : at what time does the job enter the system
runTime : the total CPU time needed by the job to finish
ioFreq : every ioFreq time units, the job issues an I/O
(the I/O takes ioTime units to complete)
Job List:
Job 0: startTime 0 - runTime 84 - ioFreq 7
Job 1: startTime 0 - runTime 42 - ioFreq 2
Job 2: startTime 0 - runTime 51 - ioFreq 4
Compute the execution trace for the given workloads.
If you would like, also compute the response and turnaround
times for each of the jobs.
Use the -c flag to get the exact results when you are finished.
这将生成三个作业(如指定的那样)的随机工作负载,使用默认队列数量和一些默认设置。如果您再次运行并加上标志(-c),您将看到与上面相同的打印结果,外加以下内容
Execution Trace:
[ time 0 ] JOB BEGINS by JOB 0
[ time 0 ] JOB BEGINS by JOB 1
[ time 0 ] JOB BEGINS by JOB 2
[ time 0 ] Run JOB 0 at PRIORITY 2 [ TICKS 9 ALLOT 1 TIME 83 (of 84) ]
[ time 1 ] Run JOB 0 at PRIORITY 2 [ TICKS 8 ALLOT 1 TIME 82 (of 84) ]
[ time 2 ] Run JOB 0 at PRIORITY 2 [ TICKS 7 ALLOT 1 TIME 81 (of 84) ]
[ time 3 ] Run JOB 0 at PRIORITY 2 [ TICKS 6 ALLOT 1 TIME 80 (of 84) ]
[ time 4 ] Run JOB 0 at PRIORITY 2 [ TICKS 5 ALLOT 1 TIME 79 (of 84) ]
[ time 5 ] Run JOB 0 at PRIORITY 2 [ TICKS 4 ALLOT 1 TIME 78 (of 84) ]
[ time 6 ] Run JOB 0 at PRIORITY 2 [ TICKS 3 ALLOT 1 TIME 77 (of 84) ]
[ time 7 ] IO_START by JOB 0
IO DONE
[ time 7 ] Run JOB 1 at PRIORITY 2 [ TICKS 9 ALLOT 1 TIME 41 (of 42) ]
[ time 8 ] Run JOB 1 at PRIORITY 2 [ TICKS 8 ALLOT 1 TIME 40 (of 42) ]
[ time 9 ] Run JOB 1 at PRIORITY 2 [ TICKS 7 ALLOT 1 TIME 39 (of 42) ]
...
Final statistics:
Job 0: startTime 0 - response 0 - turnaround 175
Job 1: startTime 0 - response 7 - turnaround 191
Job 2: startTime 0 - response 9 - turnaround 168
Avg 2: startTime n/a - response 5.33 - turnaround 178.00
]
跟踪以毫秒到毫秒的时间尺度精确地显示调度器决定做什么。
在本例中,它从运行作业0 开始,运行7毫秒,直到作业0发出一个I/O;这是完全可以预测的,因为作业0的I/O频率被设置为7毫秒,这意味着它每运行7毫秒,就会发出一个I/O,并等待它完成后再继续。
此时,调度器切换到作业1,作业1在发出I/O之前只运行2毫秒。
调度程序以这种方式打印整个执行跟踪,最后还计算每个作业的响应和周转时间以及平均值。
你还可以控制模拟的其他各个方面。
例如,你可以指定系统中有多少个队列(-n)和所有这些队列的量子长度(-q);
如果你想要更多的控制和变化量长度每队列,您可以指定长度的量子- Q(时间片)为每个队列:
如q [10, 20、30]模拟与三个队列调度器,最高优先级队列的10 ms时间片,下一级较高优先级的20 ms时间片,和低优先级队列30 ms的时间片。
你也可以单独控制每个队列有多少时间分配。这可以设置为所有带有-a的队列,或每个带有-A的队列,例如-A 20、40、60将每个队列的时间分配分别设置为20ms、40ms和60ms。
如果你是随机生成作业,您还可以控制它们运行(-m)的时间,或者它们生成I/O (-M)的频率。
但是,如果您希望对系统中运行的作业的确切特征有更多的控制,可以使用-l(小写L)或 --jlist,这允许您指定希望模拟的作业的确切集合。
列表的形式为:x1,y1,z1:x2,y2,z2:…其中x是作业的开始时间,y是运行时间(即它需要多少CPU时间),z是I/O频率(即运行z ms后,作业发出一个I/O;如果z为0,则不发出I/O)。
例如,如果您想要重新创建《操作系统导论》书中图8.3中的示例,您需要指定一个作业列表,如下所示
>> python mlfq.py --jlist 0,180,0:100,20,0 -q 10
以这种方式运行模拟器将创建一个3级MLFQ,每个级别都有一个10毫秒的时间片。
创建了两个作业:
作业0在时间0开始,总运行180毫秒,从不发出I/O;
作业1从100毫秒开始,只需要20毫秒的CPU时间就可以完成,而且从来不会产生I/O。
最后,还有三个相关参数。如果将-B标记设置为非零值,那么在调用时,每N毫秒将所有作业提升到最高优先级的队列
>> python mlfq.py -B N
调度程序使用这个特性来避免本章讨论的饥饿问题。但是,它默认是关闭的。
-S标志调用旧的规则4a和4b(书中第八章提到的规则),这意味着如果一个作业在完成它的时间片之前发出一个I/O,当它继续执行时,它将在完整的时间片不变的情况下返回到相同的优先队列。这使得调度程序的游戏成为可能。
最后,您可以通过使用-i标志轻松地更改I/O的持续时间。在这个简单的模型中,默认情况下,每个I/O都需要5毫秒的固定时间,或者用这个标志设置的任何时间。
您还可以尝试使用-I标志来确定刚刚完成I/O的作业是移动到它们所在队列的头部还是尾部。