{
pid_t pid; /* fork a child process */ pid = fork();
if (pid == 0) { /* child process */ value +=15; } else { /* parent process */ /* parent will wait for the child to complete */ wait(NULL); printf(\ exit(0); } }
答:Parent :value=8
4.4在多线程程序中,以下哪些程序状态组成是被线程共享的? a.寄存值 b.堆内存 c.全局变量 d.栈内存 答:一个线程程序的线程共享堆内存和全局变量,但每个线程都有属于自己的一组寄存
值和栈内存。
4.7由图4.11给出的程序使用了Pthread的应用程序编程接口(API),在程序的第c行和第
p行分别会输出什么? #include
int value=0;
void *runner(void *param); /* the thread */
int main(int argc, char *argv[]) {
int pid;
pthread_t tid;
pthread_attr_t attr;
pid = fork();
if (pid == 0) {/* child process */
pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, NULL); pthread_join(tid, NULL);
printf(“CHILD: value = %d”, value); /* LINE C*/ }
else if (pid > 0) {/* parent process */ wait(NULL);
printf(“PARENT: value = %d”, value); /* LINE P */ } }
void *runner(void *param) { value=10;
pthread_exit(0); }
答:c行会输出10,p行会输出0
5.4考虑下列进程集,进程占用的CPU区间长度以毫秒来计算:
进程 区间时间 优先级 P1 10 3 P2 1 1 P3 2 3 P4 1 4 P5 5 2
假设在时刻0以进程P1,P2,P3,P4,P5的顺序到达。
a.画出4个Gantt图分别演示用FCFS、SJF、非抢占优先级(数字小代表优先级高)和RR(时间片=1)算法调度时进程的执行过程。 b.每个进程在每种调度算法下的周转时间是多少? c.每个进程在每种调度算法下的等待时间是多少?
d.哪一种调度算法的平均等待时间对所有进程而言最小? 答:a.甘特图 FCFS P1 1
2
3
4
5
6
7
8
9
10
P2 P3 11
12
13
P4 P5 14
15
16
17
18
19
SJF P2 P4 P3 1
2
3
4
P5 5
6
7
8
9
P1 10
11
12
13
14
15
16
17
18
19
Non-preemptive Priority P2 P5 1
2
3
4
5
6
P1 7
8
9
10
11
12
13
14
15
16
P3 17
18
P4 19
RR(quantum=1) P1 P2 P3 P4 P5 P1 P3 P5 P1 P5 P1 P5 P1 P5 P1 P1 P1 P1 P1 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
b. Turnaround Time Process P1 P2 P3 P4 P5 Average c. Waiting Time Process P1 P2 P3 P4 P5 Average FCFS 0 10 11 13 14 9.6 SJF 9 0 2 1 4 3.2 NPP 6 0 16 18 1 8.2 RR(quantum=1) 9 1 5 3 9 5.4 FCFS 10 11 13 14 19 13.4 SJF 19 1 4 2 9 7.2 NPP 16 1 18 19 6 12 RR(quantum=1) 19 2 7 4 14 9.2 d.SJF
5.5下面哪些算法会引起饥饿
a.先来先服务
b.最短作业优先调度 c.轮转法调度 d.优先级调度
答:最短作业优先调度和优先级调度算法会引起饥饿
5.7考虑一个运行10个I/O约束(型)任务和一个CPU约束(型)任务的系统。假设,I/O约束任务每进行1毫秒的CPU计算发射一次I/O操作,但每个I/O操作的完成需要 10毫秒。同时,假设上下文切换要0.1毫秒,所有的进程都是长进程。对一个RR调度来说,以下情况时CPU的利用率是多少: a.时间片是1毫秒 b.时间片是10毫秒
6.01在生产者和消费者问题中,信号量mutex,empty,full的作用是什么?如果对调生产者进程中的两个wait操作和两个signal操作,则可能发生什么情况?
答:a.时间片是1毫秒:不论是哪个进程被调度,这个调度都会为每一次的上下文切换花费一个0.1毫秒的上下文切换。CPU的利用率是1/1.1*100=92%。
b.时间片是10毫秒:这I/O限制任务会在使用完1毫秒时间片后进行一次上下文切换。这个时间片要求在所有的进程间都走一遍,因此,10*1.1+10.1(因为每个I / O限定任务执行为1毫秒,然后承担上下文切换的任务,而CPU限制任务的执行10毫秒在承担一个上下文切换之前) 。因此,CPU的利用率是20、21.1*100=94%。
答:信号量mutex的作用是保证各生产者进程和消费者进程对缓冲池的互斥访问。信号量empty和full均是资源信号量,它们分别对应于缓冲池中的空闲缓冲区和缓冲池中的产品,生产者需要通过wait(empty)来申请使用空闲缓冲区,而消费者需要通过wait(full)才能取得缓冲中的产品,可见,这两个信号量起着同步生产者和消费者的作用,它们保证生产者不会将产品存放到满缓冲区中,而消费者不会从空缓冲区中取产品。
在生产者—消费者问题中,如果将两个wait操作,即wait(full)和wait(mutex)互换位置,或者wait(empty)和wait(mutex)互换位置,都可能引起死锁。考虑系统中缓冲区全满时,若一生产者进程先执行了wait(mutex)操作并获得成功,当再执行wait(empty)操作时,它将因失败而进入阻塞状态,它期待消费者执行signal(empty)来唤醒自己,在此之前,它不可能执行signal(mutex)操作,从而使企图通过wait(mutex)进入自己的临界区的其他生产者和所有的消费者进程全部进入阻塞状态,系统进入死锁状态。类似地,消费者进程若先执行wait(mutex),后执行wait(full)同样可能造成死锁。
signal(full)和signal(mutex)互换位置,或者signal(empty)和signal(mutex)互换位置,则不会引起死锁,其影响只是使某个临界资源的释放略为推迟一些。
6.02 一组合作进程,执行顺序如下图。请用wait、signal操作实现进程间的同步操作。
P2 P4 P6 P1 P5 P3 各进程的执行顺序
答:如图示并发进程之间的前趋关系,为了使上述进程同步,可设置8个信号量a、b、c、d、e、f、g、h,它们的初值均为0,而相应的进程可描
P1 述为(其中“?”表示进程原来的代码):
b a main( )
cobegin{
P3 P2 d e
f c P1( ) { ?; signal(a); signal(b); }
P2( ){ wait(a); ?; signal(c); signal(d); }
P4 P5 P3( ){ wait(b); ?; signal(e); signal(f); }
g h P4( ){ wait(c); wait(e); ?; signal(g); }
P6 P5( ){ wait(d); wait(f); ?; signal(h); }
P6( ){ wait(g); wait(h); ?; }
合作进程的前趋图
}coend
6.03在生产者和消费者问题中,多个生产者进程(Producer Process)和多个消费者进程
(Consumer Process)共享一个大小为8的缓冲区,他们的信号量和共享变量设置如下:
int nextc=0, nextp=0, buf[8]; semaphore full; empty; mutex;
生产者进程和消费者进程问题的算法描述如下: Producer Process: Consumer Process: int itemp; int itemc; while(1){ while(1){ 1 itemp = rand(); // Generate a number 1 wait(full); 2 wait(empty); 2 wait(mutex); 3 wait(mutex); 3 itemc=buf[nextc]; 4 buf[nextp]=itemp; 4 nextc=(nextc+1)%8; 5 nextp=(nextp+1)%8; 5 signal(mutex); 6 signal(mutex); 6 signal(empty); 7 signal(full); 7 cout << itemc << endl; } }
(1)生产者进程和消费者进程的临界区是哪些? (2)信号量full、empty和mutex的初值是多少?
(3)如果对调生产者进程中的两个P操作即第2行和第3行,以及对调消费者进程中的两个P操作即第1行和第2行,如下所示。可能发生什么情况? Producer Process Consumer Process … … 1 itemp = rand(); // Generate a number 1 wait(mutex); 2 wait(mutex); 2 wait(full); 3 wait(empty); 3 itemc=buf[nextc]; … …
(4)上面的生产者和消费者同步算法有一个缺点,在有空缓冲区时,当消费者进程正在临界区时,生产者进程必须等待,反之亦然。您如何可以解决这个问题,以提高生产者和消费者进程之间并发?写出新的生产者进程和消费者进程的同步算法。
答:(1)生产者进程的临界区是第4行和第5行;消费者进程的临界区是第3行和第4行。 (2)信号量full、empty和mutex的初值分别是:
empty = 8 , full = 0 , mutex = 1 。
(3)系统可能会产生死锁。例如,生产者进程得到信号量mutex,但是没有空缓冲区即empty≤0时,此时生产者进程阻塞;而消费者进程又无法得到信号量mutex,此时消费者进程也阻塞,系统产生了死锁。
(4)增加一个信号量mutex1,初值为1,其算法如下:
Producer Process Consumer Process int itemp; int itemc; while(1){ while(1){ 1 itemp = rand(); // Generate a number 1 wait(full); 2 wait(empty); 2 wait(mutex); 3 wait(mutex1); 3 itemc=buf[nextc]; 4 buf[nextp]=itemp; 4 nextc=(nextc+1)%8; 5 nextp=(nextp+1)%8; 5 signal(mutex);