本试题参考 @甘晴void 的CSDN博客【2.2】操作系统OS_甘晴void的博客-CSDN博客,本意为期中复习自用,答案在其基础上进行进一步完善,若有错误还请指正!
第一题:基础题(20分)
1.1(4分)
进程状态一共有多少个,是哪些?哪些状态只出现一次,哪些出现多次?
答:
(1)进程状态一共有5种,分别为运行态、就绪态、阻塞态、创建态、终止态。
(2)其中,创建态、终止态只出现一次;
运行态、就绪态、阻塞态出现多次。
1.2(4分)
请结合进程状态转移图来说明,
答:
(1)进程状态转移图如下图所示(参考王道操作系统P37):
(2)其中,
抢占式:运行态→阻塞态
非抢占式:就绪态→运行态、阻塞态→就绪态
参考来源:
1.3(4分)
fork()与exec()调用的区别?
答:
(1)系统调用fork()用于创建子进程,得到两个返回值。新创建的子进程直接从fork()系统调用返回。父进程和子进程代码和数据段相同,但pid和内存空间不同。
(2)系统调用exec()并没有创建新进程,而是直接将当前运行的程序替换为不同的程序。并且,对exec()的成功调用永远不会返回。
1.4(8分)
基于抢占式的调度,优先权值越小表示越优先,运行调度程序和进程切换用时1μs。从0开始调度程序,问平均周转时间为多少?
到达时间 | CPU耗时 | 优先权值 | |
P1 | 2μs | 12μs | 10 |
P2 | 1μs | 24μs | 30 |
P3 | 0μs | 36μs | 20 |
答:
P3的周转时间 = 完成时间 - 到达时间 = 36μs + 12μs + 3μs(切换) - 0μs = 51μs
P2的周转时间 = 完成时间 - 到达时间 = (36μs + 24μs + 12μs + 4μs) - 1μs = 75μs
P1的周转时间 = 完成时间 - 到达时间 = (2μs + 1μs + 12μs) - 2μs = 13μs
平均周转时间 = (P3的周转时间 + P2的周转时间 + P1的周转时间) / 进程数量
= (51μs + 75μs + 13μs) / 3
= 139μs / 3
≈ 46.33μs
所以,平均周转时间约为46.33μs。
(注意,刚开始运行时和进行进程切换时都要加上1μs)
第二题:MLFQ多级反馈队列(10分)
五条规则及其相应作用?
答:
五条规则:
规则1.如果A的优先级 > B的优先级,运行A(不运行B)
规则2.如果A的优先级 = B的优先级,轮转运行A和B
规则3.工作进入系统时,放在最高优先级(最上层队列)
规则4.一旦工作用完了其在某一层中的时间配额(无论中间主动放弃了多少次CPU),就降低其优先级(移入低一级队列)
规则5.经过一段时间S,就将系统中所有工作重新加入最高优先级队列
(见《操作系统导论》P63)
第三题:彩票调度与步长调度(20分)
3.1
写出彩票的意义,问彩票数与步长的关系
答:
(1)彩票数代表进程占有某个资源的份额
(2)步长与彩票数成反比
3.2
若ABC彩票数分别是200,300,500。给定整数60000,求出各自的票数
答:
A的彩票数为12000
B的彩票数为18000
C的彩票数为30000
3.3
模拟一遍,直至各自里程再次相同
答:
假设选择A先运行,
行程值(A)步长=300 行程值(B)步长=200 行程值(C)步长=120 谁运行 0 0 0 A 300 0 0 B 300 200 0 C 300 200 120 C 300 200 240 B
300 400 240 C 300 400 360 A 600 400 360 C 600 400 480 B 600 600 480 C 600 600 600 ……
3.4
求出各自的CPU占比
答:
CPU占比2:3:5
第四题:僵尸进程(20分)
4.1
运行以下代码,写出输出结果(pid整数可以自定,但前后要自洽)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main()
{
printf("hello world (pid:%d)\n", (int)getpid());
pid_t pid;
int count = 0;
pid = fork();
if (pid < 0)
{
printf("error occurred!\n");
}
else if (pid == 0)
{
printf("%d son %4d\n", getppid(), getpid());
count++;
exit(0);
}
else
{
sleep(5);
wait(NULL);
printf("%d father %4d\n", getppid(), getpid());
count++;
}
printf("count = %d\n",count);
return 0;
}
答:
原因:
在子进程中,count被设置为1,但子进程随后退出,这个值不会被父进程看到。
在父进程中,count也被设置为1(因为父进程有自己的count副本)。
因此,当父进程打印count的值时,它显示的是1,而不是2(即使子进程也增加过count)。这是因为两个进程对count的修改是隔离的,父进程无法看到子进程对count的修改。
4.2
结合僵尸进程与孤儿进程的概念。这段代码会产生僵尸进程还是孤儿进程?如果是孤儿进程,请修改代码使其产生僵尸进程;如果是僵尸进程,请修改代码使其产生孤儿进程
答:
(1)这段代码会产生僵尸进程
原因:子进程结束时,父进程还处于sleep(5)状态,还在睡觉,暂时没有把子进程收回,导致僵尸进程的产生。但是,父进程睡了5ms,睡醒之后立刻把子进程收回了,所以僵尸进程只产生了5ms。我感觉吧,这题的意思是,只要产生过,就是有,这个程序就有问题,所以是僵尸进程。
(2)要将僵尸进程改成孤儿进程,就要让父进程先于子进程结束。可以将sleep(5)改为放在子进程那边,exit也换个位置。
代码如下:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main() { printf("hello world (pid:%d)\n", (int)getpid()); pid_t pid; int count = 0; pid = fork(); if (pid < 0) { printf("error occurred!\n"); } else if (pid == 0) { sleep(5); printf("%d son %4d\n", getppid(), getpid()); count++; } else { printf("%d father %4d\n", getppid(), getpid()); count++; exit(0); } printf("count = %d\n",count); return 0; }
第五题:作业题(10分)
题目提供了./process-run -l 4:100 -s 3 -c和./process-run -l 4:0 -s 3 -c的运行截图
要求我们写出./process-run -l 4:50 -s 3 -c的运行截图
答:
因为占用cpu运行的指令数为4,使用cpu概率为50%,所以就是cpu→io→cpu→io(其他情况也行,均分即可),如下图所示:
第六题:实验题
实验自2024年已改版,所以2023年实验题没有参考价值,不再赘述。