错题本第二章 进程管理
本文持续更新中
单项选择题
P39 5. 下面的叙述中,正确的是()。
A. 进程获得处理器运行时通过调度得到的
B. 优先级是进程调度的重要依据,一旦确定不能改动
C. 在单处理器系统中,任何时刻都只有一个进程处于运行态
D. 进程申请处理器而得不到满足时,其状态变为阻塞态
- 正确答案:A
- 错误答案:C
- 考点:
- 第二章 进程的描述与控制:进程状态的状态及转换
- 解析:在单处理器系统中,如果发生死锁,进程就全部处于阻塞态;系统中没有进程时,也没有进程处于运行态。
P39 9. 一个进程释放了一台打印机,它可能会改变()的状态。
A. 自身进程
B. 输入/输出进程
C. 另一个等待打印机的进程
D. 所有等待打印机的进程
- 正确答案:C
- 错误答案:A
- 考点:
- 第二章 进程的描述与控制:进程的状态及转换
- 解析:由于打印机独占资源,一个进程释放打印机后另一个等待打印机的进程可能会从阻塞态转为就绪态。
P40 20. 若一个进程实体由PCB、共享正文段、数据堆段和数据栈段组成,请指出下列C语言程序中的内容及相关数据结构各位于哪一段中。
I. 全局赋值变量()
II. 未赋值的局部变量()
III. 函数调用实参传递值()
IV. 用malloc()要求动态分配的存储区()
V. 常量值(如1995、"string")()
VI. 进程的优先级()
A. PCB
B. 正文段
C. 堆段
D. 栈段
- 正确答案:BDDCBA
- 错误答案:CDDBCA
- 考点:
- 第二章 进程的描述与控制:进程的组织
- 解析:C语言编写的程序在使用内存时一般分为三个段,为:正文段:代码和赋值数据段、数据堆段、数据栈段。其中,二进制代码和常量存放在正文段,动态分配的存储区在数据堆段,局部变量在数据栈段。所以,全局赋值变量和常量值在正文段,未赋值的局部变量和函数参数的传递值在数据栈段,用malloc()动态分配的存储区在数据堆段,进程的优先级在PCB中。
P40 22. 系统动态DLL库中的系统线程,被不同的进程所调用,它们是()的线程。
A. 不同
B. 相同
C. 可能不同,可能相同
D. 不能被调用
- 正确答案:B
- 错误答案:A
- 考点:
- 第二章 进程的描述与控制:线程的实现方式
- 解析:同一个系统的进程或线程可能被不同的进程或线程调用,所以系统动态DLL库中的线程不管被什么进程调用,它们都是相同的线程。
P41 30. 下列选项中,导致创建新进程的操作是()。
I. 用户登录成功
II. 设备分配
III. 启动和程序执行
A. 仅I和II
B. 仅II和III
C. 仅I和III
D. I、II、III
- 正确答案:C
- 错误答案:D
- 考点:
- 第二章 进程的描述与控制:进程的创建
- 解析:引起进程创建的典型事件主要有:用户登录:在分时系统中,用户登录成功后操作系统将为该用户创建一个进程并插入就绪队列中;作业调度:在多道批处理系统中,当作业调度程序按一定的算法调度到某些作业时,便将它们装入内存,为它们创建进程,并将其插入就绪队列;提供服务:当运行中的用户程序提某种请求后(如要求进行文件打印等),操作系统将专门创建一个进程提供用户所需要的服务;应用请求:用户进程自己创建新进程,以便使新进程以同创建者进程并发运行的方式完成特定任务。用户登录成功和启动程序执行都是创建进程的典型事件,而设备分配则不是。设备分配是通过在系统中设置相应的数据结构实现的,不需要创建进程,这是操作系统中I/O核心子系统的内容。
P92 19. 用P,V操作实现进程同步,信号量的初值为()。
A. -1
B. 0
C. 1
D. 由用户确定
- 正确答案:D
- 错误答案:C
- 考点:
- 第二章 进程的描述与控制:经典进程的同步问题、信号量机制
- 解析:用P,V操作实现进程同步时,信号量的初值应该根据具体问题确定。例如,在生产者-消费者问题中,表示空闲缓冲区数量的信号量
empty
就应设置为空闲缓冲区的数量n,而表示消息数量的信号量full
就应设置为0。用P,V操作实现进程互斥时,信号量的初值应该设为1。
P92 20. 可以被多个进程在任意时刻共享的代码必须是()。
A. 顺序代码
B. 机器语言代码
C. 不允许任何修改的代码
D. 无转移指令的代码
- 正确答案:A
- 考点:NULL
- 解析:若代码可被多个进程在任意时刻共享,则要求任一个进程在调用此段代码时都以同样的方式运行,而且进程在运行过程中被中断后再继续执行,其执行结果不受影响。这必然要求代码不能被任何进程修改,否则无法满足共享的要求。这样的代码就是可重入代码,也称纯代码,即允许多个进程同时访问的代码。
P92 26. 一个进程因在互斥信号量mutex上执行V(mutex)操作而导致唤醒另一个进程时,执行V操作后mutex的值为()。
A. 大于0
B. 小于0
C. 大于等于0
D. 小于等于0
- 正确答案:D
- 错误答案:C
- 考点:
- 第二章 进程的描述与控制:信号量机制
- 解析:当互斥量等于0时,表示临界区已有一个进程进入,临界区外尚无进程等待;当互斥量小于0时,表示临界区中有进程,互斥量的绝对值表示在临界区外等待进入临界区的进程数。由题中“唤醒另一个进程”可知系统中存在等待进入临界区的进程,所以
mutex
小于等于-1,所以该进程执行V(mutex)
操作后,mutex
的值小于等于0。
P93 30. 下列关于管程的叙述中,错误的是()。
A. 管程只能用于实现进程的互斥
B. 管程是由编程语言支持的进程同步机制
C. 任何时候只能有一个进程在管程中执行
D. 管程中定义的变量只能被管程内的过程访问
- 正确答案:A
- 考点:
- 第二章 进程的描述与控制:管程
- 解析:管程是由编程语言提供支持的,可以用编程语言实现管程,每次仅允许一个进程进入管程,这是由编译器/解释器实现的(例如Java的synchronized关键字)。
P96 46. 属于同一进程的两个线程thread1和thread2并发执行,共享初始值为0的全局变量x。thread1和thread2实现对全局变量x加1的机器代码描述如下:
thread1:
mov R1, x // (x) -> R1
inc R1 // (R1) + 1 -> R1
mov x, R1 // (R1) -> x
thread2:
mov R2, x // (x) -> R2
inc R2 // (R2) + 1 -> R2
mov x, R2 // (R2) -> x
在所有有可能的指令执行序列中,使x的值为2的序列个数是()。
A. 1
B. 2
C. 3
D. 4
- 正确答案:B
- 错误答案:D
- 考点:NULL
- 解析:分析并发程序执行的题目可以分三步做:1. 给语句编号;2. 列出所有可能的执行序列;3. 根据共享变量的初值分析每种执行序列的结果。本题共享变量x的初值为0,所有的执行序列中只有两种最后的结果为2,即(语句按顺序编号为1-6)1-2-3-4-5-6或4-5-6-1-2-3。
P60 14. 下列调度算法中,()调度算法是绝对可抢占的。
A. 先来先服务
B. 时间片轮转
C. 优先级
D. 短进程优先
- 正确答案:B
- 错误答案:C
- 考点:
- 第三章 处理机的调度与死锁 调度算法
- 解析:题目中的“绝对可抢占”指的是该算法只能设计为抢占式的,不能设计为非抢占式的。选项中的先来先服务、优先级、短进程优先这三种调度算法都可以是非抢占的,只有时间片轮转调度算法一定是抢占式的。
P60 18. 有以下进程需要调度执行(见下表):
- 若采用非抢占式短进程优先调度算法,问这5个进程的平均周转时间是多少?
- 若采用抢占式短进程优先调度算法,问这5个进程的平均周转周期是多少?
A. 8.62; 6.34
B. 8.62; 6.8
C. 10.62; 6.34
D. 10.62; 6.8
进程名 | 到达时间 | 运行时间 |
---|---|---|
P1 | 0.0 | 9 |
P2 | 0.4 | 4 |
P3 | 1.0 | 1 |
P4 | 5.5 | 4 |
P5 | 7 | 2 |
- 正确答案:D
- 考点:
- 第三章 处理机的调度与死锁 平均周转时间的计算
- 解析:此类题型可以画广义甘特图来求解。非抢占式短进程优先调度算法的广义甘特图如下:
可计算出平均周转时间为(9 + (16 - 0.4) + (10 - 1) + (20 - 5.5) + (12 - 7))/ 5 = 10.62
抢占式短进程优先调度算法的广义甘特图如下:
image可以计算出平均周转时间为(20 + 5 + 1 + 6 + 2)/ 5 = 6.8
P61 28. 若某单处理器多进程系统中有多个就绪态进程,则下列关于处理机调度的叙述中,错误的是()。
A. 在进程结束时能进行处理机调度
B. 创建新进程后能进行处理机调度
C. 在进程处于临界区时不能进行处理机调度
D. 在系统调用完成并返回用户态时能进行处理机调度
- 正确答案:C
- 考点:
- 第三章 处理机的调度与死锁 处理机调度的时机、切换与过程
- 解析:不能进行进程的调度与切换的情况有三种:1. 在处理中断的过程中;2. 进程在操作系统内核程序临界区中;3. 其他需要完全屏蔽中断的原子操作过程中。A、B、D显然是可以进行处理机调度的情况,而根据以上知识点,只有进程在操作系统内核程序临界区中时才不能进行处理机调度。所以,进程在其他临界区时可以进行处理机调度。
P134 31. 系统中有三个不同的临界资源R1,R2和R3,被4个进程P1,P2,P3,P4共享。各进程对资源的需求为:P1申请R1和R2,P2申请R2和R3,P3申请R1和R3,P4申请R2。若系统出现死锁,则处于死锁状态的进程数至少是()。
A. 1
B. 2
C. 3
D. 4
- 正确答案:C
- 解析:对于本题,先满足一个进程的资源需求,再看其他进程是否出现死锁。因为P4只申请一个资源,当将R2分配给P4后,P4执行完将R2释放,这时使得系统满足死锁的条件是R1分配给P1,R2分配给P2,R3分配给P3(或者R2分配给P1,R3分配给P2,R1分配给P3)。穷举其他情况如P1申请的资源R1和R2,先都分配给P1,运行完并释放占有的资源后,可分别将R1,R2和R3分配给P3,P4和P2,也满足系统死锁的条件。各种情况需要使得处于死锁状态的进程数至少为3。
- 疑惑:这里为什么把R2分配给了P4还会三个进程死锁?P4不是只需要R2么,把R2分配给了P4之后P4不就可以运行了吗?
P134 32. 若系统S1采用死锁避免方法,S2采用死锁检测方法。下列叙述中,正确的是()。
I. S1会限制用户申请资源的顺序,而S2不会
II. S1需要进程运行所需的资源总量信息,而S2不需要
III. S1不会给可能导致死锁的进程分配资源,而S2会
A. 仅I、II
B. 仅II、III
C. 仅I、III
D. I、II、III
- 正确答案:B
- 考点:
- 第三章 处理机的调度与死锁:死锁预防、死锁避免(银行家算法)
- 解析:银行家算法是死锁避免算法,系统在执行安全性算法中都会检查此次资源试分配后系统是否处于安全状态,若不安全则将本次试探分配作废。银行家算法不会限制用户申请资源的顺序,需要限制用户申请资源的顺序的是死锁预防中破坏循环等待条件中采用的顺序资源分配法,即首先给系统中的资源进行编号,规定每个进程必须按编号递增的顺序请求资源,同类资源一次申请完。这属于死锁预防的范畴,所以I不正确。
综合应用题之进程同步大题
P97 6. 在一个仓库中可以存放A和B两种产品,要求:
- 每次只能存入一种产品。
- A产品数量-B产品数量 < M。
- B产品数量-A产品数量 < N。
其中M、N是正整数,试用P操作、V操作描述产品A与产品B的入库过程。
- 考点:吸烟者问题
- 核心思路:这道题其实应该把A-B和B-A视为两个整体,而不应该把A和B视为两个整体,因为A-B的值即为仓库中还能容纳A产品的数量,B-A的值即为仓库中还能容纳B产品的数量,而生产一个A产品会导致A产品容纳量减1、B产品容纳量加1,生产一个B产品则刚好相反,按照这个思路来模拟,这道题就很简单了。这个思路类似于吸烟者问题中设定信号量时应该将三种材料的三种组合视为三个整体而不是三种材料分别考虑的思路。
- 解答:
semaphore a = M - 1; // A - B,即仓库中还可容纳多少个A产品
semaphore b = N - 1; // B - A,即仓库中还可容纳多少个B产品
semaphore mutex = 1; // 用于互斥访问仓库
A() { // A产品的入库过程
while (1) {
P(a); // 仓库中还可容纳A产品的数量-1
P(mutex);
A产品入库;
V(mutex);
V(b); // 仓库中还可容纳B产品的数量+1
}
}
B() { // B产品的入库过程
while (1) {
P(b); // 仓库中还可容纳B产品的数量-1
P(mutex);
B产品入库;
V(mutex);
V(a); // 仓库中还可容纳A产品的数量+1
}
}
P97 7. 面包师有很多面包,由n名销售人员销售。每名顾客进店后取一个号,并且等待叫号;当一名销售人员空闲时,就叫下一个号。试设计一个使销售人员和顾客同步的算法。
- 考点:读者-写者问题
- 疑问:题目中给的n在标准答案中没有用上,这个n到底有没有实际用处?(实际上我看懂标准答案了,但是似懂非懂,不懂的地方主要就集中在这个n到底有没有用上。做题的时候想到了记录叫号值和取号值和对这两个值的互斥访问,但是做完题看到标准答案里n没用上就懵了,并且标准答案里也没有表现出“当一名销售人员空闲时,就叫下一个号”和“顾客等待叫号”,个人认为这里应该需要再多一对P、V操作才比较符合题目中的逻辑)
-
核心思路:这道题的核心思路(叫号的逻辑)类似于读者-写者问题中读者进程计数变量
count
的设置和加锁保护,但是没有该问题中“第一个进程加锁,最后一个进程解锁”的逻辑。只需要设置两个变量记录当前取号和当前叫号,再设置两个信号量对这两个计数变量进行加锁保护即可。 - 解答:
int i = 0, j = 0; // i为下一名顾客要取走的号,j为下一个要叫的号
semaphore mutex_i = 1; // 互斥访问i
semaphore mutex_j = 1; // 互斥访问j
customer() { // 顾客
while (1) {
走进面包店;
P(mutex_i); // 获取变量i的锁
取走i号;
i++;
V(mutex_i); // 释放i的锁
等待叫号; 买面包;
}
}
seller() {
while (1) {
P(mutex_j); // 获取j的锁
if (i >= j) { // i >= j说明j号已经被顾客取走,此时有顾客在等待
叫号j;
j++;
V(mutex_j); // 释放j的锁
把面包卖给顾客;
} else {
V(mutex_j); // 没有顾客在等待,释放j的锁
休息片刻;
}
}
}
P98 10. 某寺庙有小和尚、老和尚若干,有一水缸,由小和尚提水入缸供老和尚饮用。水缸可容10桶水,水取自同一井中。水井径窄,每次只能容一个桶取水。水桶总数为3个。每次入缸取水仅为一桶水,且不可同时进行。试给出有关从缸取水,入水的算法描述。
- 考点:生产者-消费者问题
- 核心思路:这道题类似于生产者-消费者问题:易错点在于防止死锁,因为题目中有三个临界资源:水缸、水桶、井,在访问临界资源时要特别注意P操作的顺序,避免因顺序错误而产生死锁。
- 错误答案:
semaphore bucket = 3; // 表示有多少个水桶可以用
semaphore empty = 10; // 表示水缸中还能容纳几桶水
semaphore full = 0; // 表示水缸中已经装有几桶水
semaphore mutex1 = 1; // 用于互斥地访问水缸
semaphore mutex2 = 1; // 用于互斥地访问水井
老和尚() {
while (1) {
P(full);
P(bucket);
P(mutex1);
从水缸中打一桶水;
V(mutex1);
V(empty);
V(bucket); // 错误点1:应该在喝水之后再释放水桶
喝水;
}
}
小和尚() {
while (1) {
P(bucket);
P(mutex2);
从井中打一桶水;
V(mutex2);
P(empty); // 错误点2:这句应该放到最前面,若放在这里会产生死锁:当水缸全部装满、水桶全在小和尚手里且装满水时就会产生死锁。为了避免死锁,应该在开头使用P(empty)判断水缸中是否还能装水,如果不能装水则需要等待
P(mutex1);
把水倒入水缸;
V(mutex1);
V(full);
V(bucket);
}
}
- 正确答案:
semaphore well = 1; // 用于互斥地访问水井
semaphore vat = 1; // 用于互斥地访问水缸
semaphore empty = 10; // 用于表示水缸中剩余空间能容纳的水的桶数
semaphore full = 0; // 表示水缸中水的桶数
semaphore pail = 3; // 表示有多少个水桶可以用,初值为3
老和尚() {
while (1) {
P(full);
P(pail);
P(vat);
从水缸中打一桶水;
V(vat);
V(empty);
喝水;
V(pail);
}
}
小和尚() {
while (1) {
P(empty);
P(pail);
P(well);
从井中打一桶水;
V(well);
P(vat);
将水倒入水缸中;
V(vat);
V(full);
V(pail);
}
}
P99 16. 设P、Q、R共享一个缓冲区,P,Q构成一对生产者-消费者,R既为生产者又为消费者。使用P、V操作实现其同步。
- 考点:生产者-消费者问题
-
核心思路:这道题其实一点也不难,但是我错在了对进程R的行为的识别上。R既为生产者又为消费者,因此必须在执行具体操作前判断状态,若
empty == 1
,则执行生产者功能;若full == 1
,则执行消费者功能。 - 错误答案:
semaphore mutex = 1; // 用于互斥地访问缓冲区
semaphore empty = 1; // 用于表示缓冲区剩余空间大小
semaphore full = 0; // 用于表示缓冲区中已有的消息数量
P() {
while (1) {
生产一个消息;
P(empty);
P(mutex);
把消息放入缓冲区;
V(mutex);
V(full);
}
}
Q() {
while (1) {
P(full);
P(mutex);
从缓冲区取消息;
V(mutex);
V(empty);
消费消息;
}
}
R() {
while (1) {
生产一个消息;
P(empty);
P(mutex);
把消息放入缓冲区;
V(mutex);
V(full);
P(full);
P(mutex);
从缓冲区取消息;
V(mutex);
V(empty);
消费消息;
}
}
- 正确答案:
semaphore mutex = 1; // 用于互斥地访问缓冲区
semaphore empty = 1; // 用于表示缓冲区剩余空间大小
semaphore full = 0; // 用于表示缓冲区中已有的消息数量
P() {
while (1) {
生产一个消息;
P(empty);
P(mutex);
把消息放入缓冲区;
V(mutex);
V(full);
}
}
Q() {
while (1) {
P(full);
P(mutex);
从缓冲区取消息;
V(mutex);
V(empty);
消费消息;
}
}
R() {
while (1) {
if (empty == 1) {
生产一个消息;
P(empty);
P(mutex);
把消息放入缓冲区;
V(mutex);
V(full);
}
if (full == 1) {
P(full);
P(mutex);
从缓冲区取消息;
V(mutex);
V(empty);
消费消息;
}
}
}
网友评论