第四章课后题
课后实验在github上——指导书纯英文无汉化,罢了罢了
第1题
用以下标志运行程序:
./process-run.py -l 5:100,5:100CPU 利用率(CPU 使用时间的百分比)应该是多少?为什么你知道这一点?
利用
-c标记查看你的答案是否正确。
先看一眼README,说此程序是用来看进程状态是如何随着运行变化的,列出了四种状态,running ready blocked done,
输入操作数和CPU占比,模拟os的实际时间片分配
回到题目,指令的意思是两个进程,各5条指令,不涉及io操作,cpu使用率还是100%
Time PID: 0 PID: 1 CPU IOs
1 RUN:cpu READY 1
2 RUN:cpu READY 1
3 RUN:cpu READY 1
4 RUN:cpu READY 1
5 RUN:cpu READY 1
6 DONE RUN:cpu 1
7 DONE RUN:cpu 1
8 DONE RUN:cpu 1
9 DONE RUN:cpu 1
10 DONE RUN:cpu 1
没问题
第二题
现在用这些标志运行:./process-run.py -l 4:100,1:0。这些标志指定了一个包含 4 条指令的进程(都要使用 CPU),并且只是简单地发出 I/O 并等待它完成。完成这两个进程需要
多长时间?利用-c 检查你的答案是否正确。
两个进程,第一个4指令无io,4时钟周期,另一个是一个io指令
# python ./process-run.py -l 4:100,1:0
Produce a trace of what would happen when you run these processes:
Process 0
cpu
cpu
cpu
cpu
Process 1
io
io_done
Important behaviors:
System will switch when the current process is FINISHED or ISSUES AN IO
After IOs, the process issuing the IO will run LATER (when it is its turn)
也就是说一个io需要发起异常、完成两个时间周期,以及一个io操作?
# python ./process-run.py -l 4:100,1:0 -c
Time PID: 0 PID: 1 CPU IOs
1 RUN:cpu READY 1
2 RUN:cpu READY 1
3 RUN:cpu READY 1
4 RUN:cpu READY 1
5 DONE RUN:io 1
6 DONE BLOCKED 1
7 DONE BLOCKED 1
8 DONE BLOCKED 1
9 DONE BLOCKED 1
10 DONE BLOCKED 1
11* DONE RUN:io_done 1
CPU用时6,周期,等待io阻塞了5周期,累积是11周期
第三题
现在交换进程的顺序:./process-run.py -l 1:0,4:100。现在发生了什么?交换顺序是否
重要?为什么?同样,用-c 看看你的答案是否正确。
应该是在阻塞期间运行了无io的进程,直接看答案吧:
# python ./process-run.py -l 1:0,4:100 -c
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED RUN:cpu 1 1
3 BLOCKED RUN:cpu 1 1
4 BLOCKED RUN:cpu 1 1
5 BLOCKED RUN:cpu 1 1
6 BLOCKED DONE 1
7* RUN:io_done DONE 1
猜想完全正确
第四题
现在探索另一些标志。一个重要的标志是-S,它决定了当进程发出 I/O 时系统如何
反应。将标志设置为 SWITCH_ON_END,在进程进行 I/O 操作时,系统将不会切换到另一
个进程,而是等待进程完成。当你运行以下两个进程时,会发生什么情况?一个执行 I/O,
另一个执行 CPU 工作。(-l 1:0,4:100 -c -S SWITCH_ON_END)
阻塞了调度呗
# python ./process-run.py -l 1:0,4:100 -c -S SWITCH_ON_END
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED READY 1
3 BLOCKED READY 1
4 BLOCKED READY 1
5 BLOCKED READY 1
6 BLOCKED READY 1
7* RUN:io_done READY 1
8 DONE RUN:cpu 1
9 DONE RUN:cpu 1
10 DONE RUN:cpu 1
11 DONE RUN:cpu 1
没有问题,io操作的阻塞期间没被调度走
第五题
现在,运行相同的进程,但切换行为设置,在等待 I/O 时切换到另一个进程(-l 1:0,4:100
-c -S SWITCH_ON_IO)。现在会发生什么?利用-c 来确认你的答案是否正确。
预期:和最初等价,即阻塞期间被调度走
# python ./process-run.py -l 1:0,4:100 -c -S SWITCH_ON_IO
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED RUN:cpu 1 1
3 BLOCKED RUN:cpu 1 1
4 BLOCKED RUN:cpu 1 1
5 BLOCKED RUN:cpu 1 1
6 BLOCKED DONE 1
7* RUN:io_done DONE 1
符合预期
第六题
另一个重要的行为是 I/O 完成时要做什么。利用-I IO_RUN_LATER,当 I/O 完成时,
发出它的进程不一定马上运行。相反,当时运行的进程一直运行。当你运行这个进程组合
时会发生什么?(./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_LATER -c -p)系统资源是否被有效利用?
四个进程,一个为3次io,其余都是cpu操作,运行一下看看
python ./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_LATER -c -p
Time PID: 0 PID: 1 PID: 2 PID: 3 CPU IOs
1 RUN:io READY READY READY 1
2 BLOCKED RUN:cpu READY READY 1 1
3 BLOCKED RUN:cpu READY READY 1 1
4 BLOCKED RUN:cpu READY READY 1 1
5 BLOCKED RUN:cpu READY READY 1 1
6 BLOCKED RUN:cpu READY READY 1 1
7* READY DONE RUN:cpu READY 1
8 READY DONE RUN:cpu READY 1
9 READY DONE RUN:cpu READY 1
10 READY DONE RUN:cpu READY 1
11 READY DONE RUN:cpu READY 1
12 READY DONE DONE RUN:cpu 1
13 READY DONE DONE RUN:cpu 1
14 READY DONE DONE RUN:cpu 1
15 READY DONE DONE RUN:cpu 1
16 READY DONE DONE RUN:cpu 1
17 RUN:io_done DONE DONE DONE 1
18 RUN:io DONE DONE DONE 1
19 BLOCKED DONE DONE DONE 1
20 BLOCKED DONE DONE DONE 1
21 BLOCKED DONE DONE DONE 1
22 BLOCKED DONE DONE DONE 1
23 BLOCKED DONE DONE DONE 1
24* RUN:io_done DONE DONE DONE 1
25 RUN:io DONE DONE DONE 1
26 BLOCKED DONE DONE DONE 1
27 BLOCKED DONE DONE DONE 1
28 BLOCKED DONE DONE DONE 1
29 BLOCKED DONE DONE DONE 1
30 BLOCKED DONE DONE DONE 1
31* RUN:io_done DONE DONE DONE 1
Stats: Total Time 31
Stats: CPU Busy 21 (67.74%)
Stats: IO Busy 15 (48.39%)
可以看到pid 0 完成一次io之后就干等着,一直到pid 3执行完才继续,后续的阻塞cpu就浪费着,所以利用率不高,不合理
第七题
现在运行相同的进程,但使用-I IO_RUN_IMMEDIATE 设置,该设置立即运行发出
I/O 的进程。这种行为有何不同?为什么运行一个刚刚完成 I/O 的进程会是一个好主意?
python ./process-run.py -l 3:0,5:100,5:100,5:100 -S SWITCH_ON_IO -I IO_RUN_IMMEDIATE -c -p
Time PID: 0 PID: 1 PID: 2 PID: 3 CPU IOs
1 RUN:io READY READY READY 1
2 BLOCKED RUN:cpu READY READY 1 1
3 BLOCKED RUN:cpu READY READY 1 1
4 BLOCKED RUN:cpu READY READY 1 1
5 BLOCKED RUN:cpu READY READY 1 1
6 BLOCKED RUN:cpu READY READY 1 1
7* RUN:io_done DONE READY READY 1
8 RUN:io DONE READY READY 1
9 BLOCKED DONE RUN:cpu READY 1 1
10 BLOCKED DONE RUN:cpu READY 1 1
11 BLOCKED DONE RUN:cpu READY 1 1
12 BLOCKED DONE RUN:cpu READY 1 1
13 BLOCKED DONE RUN:cpu READY 1 1
14* RUN:io_done DONE DONE READY 1
15 RUN:io DONE DONE READY 1
16 BLOCKED DONE DONE RUN:cpu 1 1
17 BLOCKED DONE DONE RUN:cpu 1 1
18 BLOCKED DONE DONE RUN:cpu 1 1
19 BLOCKED DONE DONE RUN:cpu 1 1
20 BLOCKED DONE DONE RUN:cpu 1 1
21* RUN:io_done DONE DONE DONE 1
Stats: Total Time 21
Stats: CPU Busy 21 (100.00%)
Stats: IO Busy 15 (71.43%)
现在的策略是io结束了控制就回到pid 0继续,这样每一个io的阻塞期间都有进程运行,cpu得到了充分利用。
至于为什么运行一个刚刚完成 I/O 的进程会是一个好主意,如果认为程序有良好的局部性在一次io之后接着io的可能性比较大,那么考虑到io操作较长时间的阻塞,把其它cpu操作尽可能放在阻塞期间执行显然是好主意
第八题
现在运行一些随机生成的进程,例如-s 1 -l 3:50,3:50, -s 2 -l 3:50,3:50, -s 3 -l 3:50,3:50。
看看你是否能预测追踪记录会如何变化?当你使用-I IO_RUN_IMMEDIATE 与-I IO_RUN_
LATER 时会发生什么?当你使用-S SWITCH_ON_IO 与-S SWITCH_ON_END 时会发生什么?
先看一眼-s参数的含义:SEED, --seed=SEED the random seed 用于生成随机数的
也就是两个进程,各3个操作,期中cpu操作和io操作的概率为各50%
开放性试题,随便做几个试一试:
# python .\process-run.py -s 2 -l 3:50,3:50 -I IO_RUN_IMMEDIATE -c
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED RUN:cpu 1 1
3 BLOCKED RUN:io 1 1
4 BLOCKED BLOCKED 2
5 BLOCKED BLOCKED 2
6 BLOCKED BLOCKED 2
7* RUN:io_done BLOCKED 1 1
8 RUN:io BLOCKED 1 1
9* BLOCKED RUN:io_done 1 1
10 BLOCKED RUN:io 1 1
11 BLOCKED BLOCKED 2
12 BLOCKED BLOCKED 2
13 BLOCKED BLOCKED 2
14* RUN:io_done BLOCKED 1 1
15 RUN:cpu BLOCKED 1 1
16* DONE RUN:io_done 1
# python .\process-run.py -s 2 -l 3:50,3:50 -I IO_RUN_LATER -c
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED RUN:cpu 1 1
3 BLOCKED RUN:io 1 1
4 BLOCKED BLOCKED 2
5 BLOCKED BLOCKED 2
6 BLOCKED BLOCKED 2
7* RUN:io_done BLOCKED 1 1
8 RUN:io BLOCKED 1 1
9* BLOCKED RUN:io_done 1 1
10 BLOCKED RUN:io 1 1
11 BLOCKED BLOCKED 2
12 BLOCKED BLOCKED 2
13 BLOCKED BLOCKED 2
14* RUN:io_done BLOCKED 1 1
15 RUN:cpu BLOCKED 1 1
16* DONE RUN:io_done 1
嗯,这一组没体现出区别。io结束之后立即切换和下一次阻塞时切换两种策略的结果一致。
python .\process-run.py -s 2 -l 3:50,3:50 -S SWITCH_ON_END -c
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED READY 1
3 BLOCKED READY 1
4 BLOCKED READY 1
5 BLOCKED READY 1
6 BLOCKED READY 1
7* RUN:io_done READY 1
8 RUN:io READY 1
9 BLOCKED READY 1
10 BLOCKED READY 1
11 BLOCKED READY 1
12 BLOCKED READY 1
13 BLOCKED READY 1
14* RUN:io_done READY 1
15 RUN:cpu READY 1
16 DONE RUN:cpu 1
17 DONE RUN:io 1
18 DONE BLOCKED 1
19 DONE BLOCKED 1
20 DONE BLOCKED 1
21 DONE BLOCKED 1
22 DONE BLOCKED 1
23* DONE RUN:io_done 1
24 DONE RUN:io 1
25 DONE BLOCKED 1
26 DONE BLOCKED 1
27 DONE BLOCKED 1
28 DONE BLOCKED 1
29 DONE BLOCKED 1
30* DONE RUN:io_done 1
io结束才切换,程序变成了全异步的。-S SWITCH_ON_IO应该和前两种是一致的,也做一下:
# python .\process-run.py -s 2 -l 3:50,3:50 -S SWITCH_ON_IO -c
Time PID: 0 PID: 1 CPU IOs
1 RUN:io READY 1
2 BLOCKED RUN:cpu 1 1
3 BLOCKED RUN:io 1 1
4 BLOCKED BLOCKED 2
5 BLOCKED BLOCKED 2
6 BLOCKED BLOCKED 2
7* RUN:io_done BLOCKED 1 1
8 RUN:io BLOCKED 1 1
9* BLOCKED RUN:io_done 1 1
10 BLOCKED RUN:io 1 1
11 BLOCKED BLOCKED 2
12 BLOCKED BLOCKED 2
13 BLOCKED BLOCKED 2
14* RUN:io_done BLOCKED 1 1
15 RUN:cpu BLOCKED 1 1
16* DONE RUN:io_done 1
符合预期