《现代操作系统第四版》第二章答案.docx
《《现代操作系统第四版》第二章答案.docx》由会员分享,可在线阅读,更多相关《《现代操作系统第四版》第二章答案.docx(12页珍藏版)》请在冰豆网上搜索。
《现代操作系统第四版》第二章答案
现代操作系统第二章进程与线程习题
1.图2-2中给出了三个进程状态,在理论上,三个状态可以有六种转换,每个状态两个。
但是,图中只给出了四种转换。
有没有可能发生其他两种转换中的一个或两个?
A:
从阻塞到运行的转换是可以想象的。
假设某个进程在I/O上阻塞,而且I/O
结束,如果此时CPU空闲,该进程就可以从阻塞态直接转到运行态。
而另外一种转换(从阻塞态到就绪态)是不可能的。
一个就绪进程是不可能做任何会产生阻塞的I/O或者别的什么事情。
只有运行的进程才能被阻塞。
2.假设要设计一种先进的计算机体系结构,它使用硬件而不是中断来完成进程切换。
CPU需要哪些信息?
请描述用硬件完成进程切换的工作过程。
A:
应该有一个寄存器包含当前进程表项的指针。
当I/O结束时,CPU将把当前
的机器状态存入到当前进程表项中。
然后,将转到中断设备的中断向量,读取另一个过程表项的指针(服务例程),然后,就可以启动这个进程了。
3.当代计算机中,为什么中断处理程序至少有一部分是用汇编语言编写的?
A:
通常,高级语言不允许访问CPU硬件,而这种访问是必需的。
例如,中断处理程序可能需要禁用和启用某个特定设备的中断服务,或者处理进程堆栈区的数据。
另外,中断服务例程需要尽快地执行。
(补充)主要是出于效率方面
的考量。
中断处理程序需要在尽量短的时间内完成所需的必要处理,尽量减少
对线程/程序流造成的影响,因此大部分情况下用汇编直接编写,跳过了通用编
译过程中冗余的适配部分。
4•中断或系统调用把控制转给操作系统时,为什么通常会用到与被中断进程的
栈分离的内核栈?
A:
内核使用单独的堆栈有若干的原因。
其中两个原因如下:
首先,不希望操
作系统崩溃,由于某些用户程序不允许足够的堆栈空间。
第二,如果内核将数
据保留在用户空间,然后从系统调用返回,那么恶意的用户可能使用这些数据找出某些关于其它进程的信息。
5.—个计算机系统的内存有足够的空间容纳5个程序。
这些程序有一半的时间处于等待I/O的空闲状态。
请问CPU时间浪费的比例是多少?
A:
(0.5)八5=3.125%
6.—个计算机的RAM有4GB,其中操作系统占512MB。
所有进程都占
256MB(为了简化计算)并且特征相同。
要是CPU利用率达到99%,最大I/O等待是多少?
A:
内存中最多可放(4GB-512MB)/256MB=14个进程,设每个进程的I/O
等待占总运行时间的比例为p,则CPU利用率=1-
pM4>99%====>pv71.9%
7.多个作业能够并行运行,比它们顺序执行完成的要快。
假设有两个作业同时
开始执行,每个需要20分钟的CPU时间。
如果顺序执行,那么最后一个作业
需要多长时间可以完成?
如果并行执行又需要多长时间?
假设I/O等待占
50%。
A:
每个进程的时间为40min。
顺序执行时,最后一个作业需要80min才能
完成。
并行执行时,cpu利用率为1-pAn=75%,cpu计算时间为40min,
故总时间t=40/75%=53.33min
8.考虑一个6级多道程序系统(内存中可同时容纳6个程序)。
假设每个进程的I/O等待占40%,那么CPU利用率是多少?
A:
利用率=1-pAn=1-(0.4)A6=1-0.004096=99.6%
9.假设要从互联网上下载一个2GB大小的文件,文件内容可以从一组镜像服务器获得,每个服务器可以传输文件的一部分。
假设每个传输请求给定起始字节和结束字节。
如何用多线程优化下载时间?
A:
客户端进程可以创建单独的线程;每个线程都可以从其中一个镜像服务器获取文件的不同部分。
这有助于减少停机时间。
当然,所有线程都共享一个网络链接。
这个链接可以成为一个瓶颈,因为线程的数量变得非常大。
10.为什么图2-11a的模式不适合用于在内存使用高速缓存的文件服务器?
每
个进程可以有自己的高速缓存吗?
A:
即使是有可能实现,也是很难保持文件系统的一致性。
假设某个客户进程给服务器进程1发送请求要更新文件。
该进程更新其内存的cache项。
然后,另一个客户进程给服务器进程2发送请求读取该文件。
不幸的是,如果该文件还在cache中,服务器进程2对此毫不知情,将返回过时的数据。
如果第一个进程在缓冲后将文件写到磁盘中,而服务器进程2每次读取时检查磁盘其
缓存的备份是否是最新的,系统还可以工作,但是需要避免磁盘访问的所有缓存系统。
(个人认为,高速缓存应该每个进程共享,因为不是每个进程都需要频繁读写数据,如果每个进程都分配cache会造成资源浪费。
)
11.当一个多线程进程创建子进程时,如果子进程复制父进程的所有线程,就会出现问题:
假如夫进程中有一个线程正在等待键盘输入,现在就有两个线程在等待键盘输入,父进程和子进程各有一个。
这种问题在单线程进程中也会发生吗?
A:
不会。
如果单线程进程在键盘上阻塞,就不能创建子进程。
(而多线程进程在一个线程阻塞时可以运行另一个线程,整个进程不会因此被阻塞。
)
12.在图2-8中,给出了一个多线程Web服务器。
如果读取文件的惟一途径是
正常的阻塞read系统调用,那么Web服务器应该使用用户级线程还是内核级线程?
为什么?
A:
当工作者线程从磁盘读取Web页时,它就会被阻塞。
如果使用用户级线程,该动作将阻塞整个进程,而破坏多线程的价值。
这就是使用内核线程的原因:
某些线程的阻塞不会影响到其他线程。
13.在本章中,我们介绍了多线程Web服务器,说明它比单线程服务器和有限状态机服务器更好的原因。
存在单线程服务器更好一些的情形吗?
请举例。
A:
在多线程Web服务器中,由分派程序从网络中读入工作请求,在检查请求后,分派线程挑选一个空转的(即被阻塞的)工作线程,提交该请求。
在工作线程被唤醒后,他检查有关的请求是否在Web页面高速缓存中,这个高速缓存是所有线程否可以访问的。
如果没有,该线程开始一个从磁盘调入页面的read操作,并且阻塞知道该磁盘操作完成。
在上述线程被阻塞在磁盘操作上时,分派线程可能挑选另一个线程运行,可以有效利用CPU资源。
而在单线程
服务器上,只能等第一个线程完成后,才能开始第二个线程。
也存在单线程服
务器更好的情形。
如果服务器是完全CPU绑定的,则不需要多线程。
这只会增加不必要的复杂性。
假设某个百万人口区域的电话查号系统(类似于114),如
果每个(姓名,电话号码)记录为64个字符,整个的数据库则为64MB,这就很容易全部读入服务器内存中以提供快速的查询
14。
既然计算机中只有一套寄存器,为什么在图2-12中的寄存器集合是按每
个线程中列出而不是按每个进程列出。
A:
当一个线程停止时,它在寄存器中有值。
它们必须被保存,就像进程停止时,必须保存寄存器。
多线程和多进程没有什么不同,所以每个线程需要自己的寄存器保存区。
15.在没有时钟中断的系统中,一个线程放弃CPU后可能再也不会获得CPU
资源,那么为什么线程还要通过调用thread_yield自愿放弃CPU?
A:
进程中的线程合作。
它们彼此不敌对。
如果应用程序需要阻塞以运行得更好,那么一个线程可以调用thread_yield自愿放弃CPU。
毕竟,同一个进程中的线程的全部代码通常是一个程序员写的。
"■■■■■■■■■■■■■■■■■"■■■■■■"■■■■■■■■■■■■■""■■""■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"■•■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"■■■"■•■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■"■■""■■■■■■■■■■■■■■■■■"■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■I
16.线程可以被时钟中断抢占吗?
如果可以,在什么情形下可以?
如果不可以,为什么不可以?
A:
用户级线程不能被时钟剥夺,除非整个进程的时间片用完。
内核级线程可
以单独地被剥夺。
在后一种情况下,如果线程运行过久,时钟将中断该当前进程,因而当前线程也被中断。
内核可以自由地从同一个进程中选取其他线程运行。
17.请对使用单线程文件服务器和多线程文件服务器读取文件进行比较。
假设所
需要的数据都在块高速缓存中,获得工作请求,分派工作,并处理其余必要工作需要花费12ms。
如果在时间过去1/3时,需要一个磁盘操作,额外花费75ms,此时该线程进入睡眠。
单线程服务器每秒钟可以处理多少个请求?
多线程服务器呢?
A:
在单线程情况下,cache命中需要12ms,cache未命中需要87ms,其加权平均为2/3-12+1/387=37ms,一秒钟可以完成1s/37ms=27个.
在多线程情况下,所有磁盘等待都是重叠的,因此每个请求耗时12ms,一秒
钟可以完成1s/12ms=83.3个(个人认为这样算不太准确,因为最后的几个线程如果cache未命中的话,就需要87ms,可能是完不成的,不过这个题意翻译的不是很清楚,什么叫做“时间过去1/3时”,估计原意应该是”有1/3
的时间需要额外的磁盘操作“。
这样平均算下来也可以忽略cache未命中发生
的分布情况。
)
18.在用户态实现线程的最大的优点是什么?
最大的缺点是什么?
A:
最大的优势就是效率。
不需要陷入内核来切换线程。
最大的缺点是,如果一个线程阻塞,整个进程都会阻塞。
19.在图2-15中创建线程和线程打印消息是随机交织在一起的。
有没有方法可以严格按照以下次序运行:
创建线程1,线程1打印消息,线程1结束,创建线程2,线程2打印消息,线程2结束,以此类推;如果有,是什么方法,如果没有请解释原因。
A:
是的,这是可以做到的。
每次执行pthread-create后,主程序可以调用
pthread_join等待刚刚创建的线程退出后再创建下一个线程。
20.在讨论线程中的全局变量时,曾使用过程create_global将存储分配给指
向变量的指针,而不是变量自身。
这是必需的吗?
还是直接使用变量自身也可行?
A:
将存储分配给指针是确实必要的,因为全局变量的大小是未知的。
它可能是从字符到浮点数数组的任何类型。
如果保存其值,就不得不把其大小传递给create_global,这都没有问题,但是必须将其类型作为set_global的第二个
参数,那么read_global返回值的类型是不确定的。
21.考虑一个线程全部在用户态实现的系统,该运行时系统每秒钟获得一个时钟中断。
当某个线程正在运行时系统中执行时发生一个时钟中断,此时会出现什么问题?
你有什么解决该问题的建议吗?
A:
runtime系统可以正好在这一时刻阻塞或者解除阻塞某个线程,并且忙于处理调度队列。
此时并不适合于时钟中断处理程序开始检查该队列是否应该进行线程切换,因为它们可能处于不一致的状态。
解决方法可以是:
当进入
runtime系统后,设置一个标志。
时钟处理程序将看到该标志,并且设置其自己的标志,然后返回。
当runtime系统完成时,它将检测时钟标志,看是否有时钟中断发生,并且现在运行时钟处理程序。
22.假设一个操作系统中不存在类似于select的系统调用来提前了解在从文件、管道或设备中读取时是否安全,不过该操作系统确实允许设置报警时钟,以便中断阻塞的系统调用。
在上述条件下,是否有可能在用户态中实现一个线程包?
请讨论。
A:
这是可能的,不过效率很低。
线程想要做一个系统调用,首先设定警报定时器,然后才执行调用。
如果线程阻塞,定时器将控制归还给线程包。
当然,大多数调用是不阻塞的,而定时器必须被清除。
每个可能被阻塞的系统调用都必须作为3个系统调用来执行。
如果定时器过早失效,各种问题都可能发生。
用这种方法建立线程包并不好。
23.两个进程在一个共享内存的多处理器(两个CPU)上运行,当他们要共享
一块内存时,图2-23中使用turn变量的忙等待解决方案还有效吗?
A:
仍然有效,但也仍旧是忙等待。
24.在抢占式进程调度的条件下,图2-24中互斥问题的Peterson解法可行
吗?
如果是非抢占式调度呢?
A:
对抢占式调度可行。
事实上,这种解法就是为它设计的。
而对于非抢占式调度,可能会失败。
考虑这种情况:
turn被初始化为0,但进程1先开始运行了,它就会一直循环,但不释放CPU,具有忙等待的缺点。
2523.4节中所讨论的优先级反转问题在用户级线程中是否可能发生?
为什
么?
A:
当低优先级进程位于其临界区,而高优先级进程就绪并且被调度时,将发生优先级倒置问题。
如果使用忙等待,高优先级进程将一直运行。
对于用户级线程,不可能发生低优先级线程突然被剥夺而允许高优先级线程运行,因为是不可剥夺的。
而内核级线程,就会出现这个问题。
26.2.3.4节中描述了一种有高优先级进程H和低优先级进程L的情况,导致了H陷入死循环。
若采用轮转调度算法而不是优先级调度算法,还会发生这样问题吗?
请讨论。
A:
不会发生这样的问题。
在轮转调度算法下。
L迟早会运行,最终它将会离开
临界区。
关键是,在优先级调度算法下,L永远不会运行;在轮转循环下,它
定期得到一个正常的时间片,所以有机会离开其临界区。
27.在使用线程的系统中,若使用用户级线程,是每个线程一个栈还是每个进程
个栈?
如果使用内核级线程呢?
请解释
A:
每个线程都是自己调用例程,因此它必须有其自己的堆栈以保存局部变量、返回地址等等。
这一点用户级线程和内核级线程是一样的
28.在开发计算机时,通常首先用一个程序模拟执行,一次运行一条指令,多处理器也严格按此模拟。
在这种没有同时事件发生的情形下,会出现竞争条件吗?
A:
(竞争条件指多个线程或者进程在读写一个共享数据时结果依赖于它们执行的相对时间的情形。
竞争条件发生在当多个进程或者线程在读写数据时,其最终的的结果依赖于多个进程的指令执行顺序。
)是的。
模拟计算机也可以是多道程序设计的。
例如,在进程A运行时,它读取一些共享变量。
然后发生了一个模拟时钟周期和进程B运行。
它也读取相同的变量,然后对变量进行了加1操作。
当进程A运行时,如果它也对变量进行了加1操作,就发生了竞争条件。
29.将生产者-消费者问题扩展成一个多生产者-多消费者的问题,生产(消费)者都写(读)一个共享的缓冲区,每个生产者和消费者都在自己的线程中执行。
图2-28中使用信号量的解法在这个系统中还可行吗?
A:
可行。
在给定的某个时刻,只有一个生产者(消费者)可以向(从)缓冲区添加(取出)项目。
30.考虑对于两个进程P0和P1的互斥问题的解决方案。
假设变量初始值为
0。
P0的代码如下:
pl的代码是将上述代码中的0替换为1。
该方法是否能处理互斥问题中所有可能的情形?
A:
该解决方案满足互斥,因为两个流程不可能同时处于CriticalSection。
也
就是说,当turn为0时,P0可以执行其临界区,但P1不能执行。
当turn为1也有相似的情况。
但是,这假设P0必须先运行。
如果P1产生某些东西并将其放入缓冲区,那么当P0可以进入其临界区时,它会发现缓冲区为空并阻塞。
而且,该解决方案需要严格交替两个过程,这是不希望发生的。
31.一个可以屏蔽中断的操作系统如何实现信号量?
A:
执行信号量操作,操作系统首先要禁用中断。
然后,它读取信号量的值。
如果执行down操作,而信号量等于0,就将调用进程放入与信号量有关的阻塞进程列表中。
如果执行up操作,必须检测看是否有任何进程在信号量上被阻塞。
如果有一个或多个进程被阻塞,从阻塞进程的列表中移出一个,使之就绪。
当所有这些操作都完成后,就可以开启中断了。
书中的原话是:
操作系统只需在执行以下操作时暂时屏蔽全部中断:
测试信号量、更新信号量以及在需要时是某个进程睡眠。
:
:
32.请说明如何仅通过二元信号量和普通机器指令实现计数信号量(即可以保
持一个任意值的信号量)。
:
:
A:
用两个二值信号量和一个计数器counter实现一个计数信号量:
M用于互斥,B用于阻塞,counter用于记录up减去down的次数,再用一个链表来记录阻塞在这个计数信号量上的进程。
down的实现:
进程先对M进行
down来获得counter、链表的独占访问权,并把counter减1。
如果counter大于等于0,直接对M进行up即可;否则,记录在链表再up,然后对B进行down从而阻塞这个进程。
up的实现:
进程同样先对M进
行down,counter力卩1,若其大于0,直接对M进行up即可;否则counter小于等于0,把链表中一个进程移出,然后对B、M依次up。
33.如果一个系统只有两个进程,可以使用一个屏障来同步这两个进程吗?
为什么?
A:
如果程序操作按阶段执行,直到两个进程都完成当前阶段才能进入下一阶段,这时就应该使用屏障。
(这个答案也有点奇怪,我认为只要这两个进程不是生产者-消费者模式就可以使用屏障。
)
34.如果线程在内核态实现,可以使用内核信号量对同一个进程中的两个线程进行同步吗?
如果线程在用户态实现呢?
假设在其他进程中没有线程必须访问该信号量。
请解释你的答案。
A:
对于内核线程,线程可以在信号量上阻塞,而内核可以运行该进程中的其它线程。
因而,使用信号量没有问题。
而对于用户级线程,当某个线程在信号量上阻塞时,内核将认为整个进程都被阻塞,而且不再执行它。
因此,在用户态线程的同步失败。
35.管程内的同步机制使用条件变量和两个特殊操作wait和signal。
一种更通
用的同步形式是只用一条原语waituntil,它以任意的布尔谓词作为参数。
例如
waituntilx<0ory+z这样就不再需要signal原语。
很显然这种方法比Hoare或BrinchHansen
方案更通用,但它从未被采用过。
为什么?
(提示:
请考虑其实现。
)
A:
其实现的代价很高。
每次在某些等待变化的进程的谓词中出现的任何变量,runtime系统都必须重新计算该谓词,以判断该进程是否能够被解锁。
而对于Hoare和BrinchHansen管程,则只需signal原语即可唤醒进程。
36.一个快餐店有四类雇员:
(1)领班,接收顿客点的菜单;
(2)厨师,准备
饭菜;(3)打包工,将饭菜装在袋子里;(4)收银员,将食品袋交给顾客并收钱。
每个雇员可被看作一个进行通信的顺序进程。
它们采用的进程间通信方式是什么?
请将这个模型与UNIX中进程联系起来。
A:
雇员之间通过消息传递进行通信:
在该例中,消息为订单、食物和袋子。
在
UNIX中,该4个进程通过管道连接。
37.假设有一个使用信箱的消息传递系统,当向满信箱发消息或从空信箱收消息时,进程都不会阻塞,相反,会得到一个错误代码。
进程响应错误代码的处理方式为一遍一遍地重试,直到成功为止。
这种方式会导致竞争条件吗?
A:
不会导致竞争条件(不会丢失任何东西),不过它是完全的忙等待。
38.CDC6600计算机使用一种称作处理器共享的有趣的轮转调度算法,它可
以同时处理多达10个I/O进程。
每条指令结束后都进行进程切换,这样进程
1执行指令1,进程2执行指令2,以此类推。
进程切换由特殊硬件完成,所以没有开销。
如果在没有竞争的条件下一个进程需要T秒钟完成,那么当有n
个进程共享处理器时完成一个进程需要多长时间?
A:
nTseconds。
39.考虑以下C代码:
1.voidmain(){
2.fork();
3.fork();
4.exit();
5.}
程序执行时创建了多少子进程?
40.Round-robin调度算法一般需要维护一个继续进程列表,每个进程在列表
中只出现一次。
如果某个进程在列表中出现两次会发生什么情况?
什么情况下可以允许多次出现?
A:
如果一个进程多次出现在列表中,在每个周期,它将得到多个时间片。
这种方法可以用来为更重要的进程提供更大的CPU份额。
但是,当进程阻塞时,
所有条目最好从可运行进程列表中删除。
41.是否可以通过分析源代码来确定进程是CPU密集型的还是I/O密集型的?
运行时如何确定?
A:
在简单的情况下是有可能通过看源代码来判断是否为I/O绑定的。
例如,程序开始时,将其所有输入文件读入到缓冲器中,这种程序通常不是I/O绑
定的;但是,对不同文件进行增量地读写(诸如编译程序)的问题很有可能是
I/O绑定的。
如果操作系统提供诸如UNIXps的命令,就可以得知被程序使用的CPU时间的量,你能把这个时间量与整个的时间比较以判断。
当然,这在你是系统中唯一的用户时最有意义。
42.请说明在Round-robin调度算法中时间片长度和上下文切换时间时怎样相
互影响的
A:
如果上下文切换时间较大,则时间时间片必须成比例大。
否则,上下文切换的开销可能相当高。
如果典型的CPU突发时间小于时间片,则选择大的时间片会导致系统效率低下。
如果上下文切换非常小或是可以忽略的,那么可以用更多的自由选择时间片。
43.对某系统进行监测后发现,在阻塞I/O之前,平均每个进程运行时间为T一次进程切换需要的时间为S,这里S实际上就是开销。
对于采用时间片长度为Q的轮转调度,请给出以下各种情况中CPU利用率的计算公式:
(a)Q=%
(b)Q>T
(c)S(d)Q=S
(e)Q趋近于0
A:
(a)T/(T+S);(b)T/(T+S);(c)Q/(Q+S);(d)1/2;(e)—>0;
44.有5个待运行作业,估计它们的运行时N分別是9,6,3,5和X。
采用哪
种次序运行这些作业将得到最短的平均响应时间?
(答案将依赖于X)
A:
最短作业优先可以使得平均响应时间最短。
0X,3,5,6,9.3<
X<5:
3,X,5,6,9.53,5,X,6,9.63,5,6,X,9.
X>9:
3,5,6,9,X.
45.有5个批处理作业A到E,它们几乎同时到达一个计算中心。
估计它们的
运行时间分別为10,6,2,4和8分钟。
其优先级(由外部设定)分别为3,5,2,1和4,其中5为最高优先级。
对于下列每种调度算法,计算其平均进程周转时间,可忽略进程切换的开销。
(a)轮转法。
(b)优先级调度。
(c)先来先服务(按照10,6,2,4,8次序运行)。
(d)最短作业优先。
对(a),假设系统具有多道程序处理能力,每个作业均公平共享CPU时间;对
(b)到(d),假设任一时刻只有一个作业运行,直到结束。
所有的作业都完全是CPU密集型作业。
A:
对于时间片轮转,在头10分钟里,每个作业获得1/5的CPU时间。
在第10分钟时,C结束。
在接下来的8分钟里,每个作业获得1/4的CPU时间,然后D完成,然后,在接下来的6分钟内,余下的3个作业各获得1/3的CPU时间,直到B结束,以此类推。
因此,5个作业的完成时间分别为是10,18,24,28和30,平均为22分钟。
对于优先级调度,5最先运行,6分钟完成。
其它作业分别在第14,24,26和30分钟完成,平均为18.8分钟。
如果作业按A->E的次序执行,则分别在第10,16,18,22和30分钟完成,