2024年4月28日发(作者:)

LAB7实验报告

实验目的:

 熟悉ucore中的进程同步机制,了解操作系统为进程同步提供的底层支持;

 在ucore中理解信号量(semaphore)机制的具体实现;

 理解管程机制,在ucore内核中增加基于管程(monitor)的条件变量(condition variable)

的支持;

 了解经典进程同步问题,并能使用同步机制解决进程同步问题

实验内容:

实验六完成了用户进程的调度框架和具体的调度算法,可调度运行多个进程。如果多个进程

需要协同操作或访问共享资源,则存在如何同步和有序竞争的问题。本次实验,主要是熟悉

ucore的进程同步机制—信号量(semaphore)机制,以及基于信

号量的哲学家就餐问题解决方案。然后掌握管程的概念和原理,并参考信号量机制,实现基

于管程的条件变量机制和基于条件变量来解决哲学家就餐问题。

在本次实验中,在kern/sync/check_sync.c中提供了一个基于信号量的哲学家就餐问题解法。

同时还需完成练习,即实现基于管程(主要是灵活运用条件变量和互斥信号量)的哲学家就

餐问题解法。哲学家就餐问题描述如下:有五个哲学家,他们的生活方式是交替地进行思考

和进餐。哲学家们公用一张圆桌,周围放有五把椅子,每人坐一把。在圆桌上有五个碗和五

根筷子,当一个哲学家思考时,他不与其他人交谈,饥饿时便试图取用其左、右最靠近他的

筷子,但他可能一根都拿不到。只有在他拿到两根筷子时,方能进餐,进餐完后,放下筷子

又继续思考。

一.练习

练习0:填写已有实验

练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码)

完成练习0后,建议大家比较一下(可用kdiff3等文件比较软件)个人完成的lab6和练习0

完成后的刚修改的lab7之间的区别,

分析了解lab7采用信号量的执行过程。执行make grade,大部分测试用例应该通过。

 请在实验报告中给出内核级信号量的设计描述,并说其大致执行流流程。

 请在实验报告中给出给用户态进程/线程提供信号量机制的设计方案,并比较说明给内

核级提供信号量机制的异同

思考题:

1.请在实验报告中给出内核级信号量的设计描述,并说其大致执行流流程。

答:

struct semaphore {

int count;

queueType queue;

};

void semWait(semaphore s)

{

--;

if ( < 0) {

/* place this process in */;

/* block this process */;

}

}

void semSignal(semaphore s)

{

++;

if (<= 0) {

/* remove a process P from */;

/* place process P on ready list */;

}

}

基于上诉信号量实现可以认为,当多个(>1)进程可以进行互斥或同步合作时,一个进程会

由于无法满足信号量设置的某条件而在某一位置停止,直到它接收到一个特定的信号(表明

条件满足了)。为了发信号,需要使用一个称作信号量的特殊变量。为通过信号量s传送信

号,信号量的V操作采用进程可执行原语semSignal(s);为通过信号量s接收信号,信号量

的P操作采用进程可执行原语semWait(s);如果相应的信号仍然没有发送,则进程被阻塞或

睡眠,直到发送完为止。

ucore中信号量参照上述原理描述,建立在开关中断机制和wait queue的基础上进行了具体

实现。信号量的数据结构定义如下:

[cpp] view plaincopy

typedef struct {

int value; //信号量的当前值

wait_queue_t wait_queue; //信号量对应的等待队列

} semaphore_t;

在ucore中最重要的信号量操作是P操作函数down(semaphore_t *sem)和V操作函数

up(semaphore_t *sem)。但这两个函数的具体实现是__down(semaphore_t *sem, uint32_t

wait_state) 函数和__up(semaphore_t *sem, uint32_t wait_state)函数,二者的具体实现描述如

下:

① __down(semaphore_t *sem, uint32_t wait_state, timer_t *timer):具体实现信号量的P操

作,首先关掉中断,然后判断当前信号量的value是否大于0。如果是>0,则表明可以获得

信号量,故让value减一,并打开中断返回即可;如果不是>0,则表明无法获得信号量,故

需要将当前的进程加入到等待队列中,并打开中断,然后运行调度器选择另外一个进程执行。

如果被V操作唤醒,则把自身关联的wait从等待队列中删除(此过程需要先关中断,完成

后开中断)。具体实现如下所示:

static __noinline uint32_t __down(semaphore_t *sem, uint32_t wait_state) {

bool intr_flag;

local_intr_save(intr_flag);

if (sem->value > 0) {

sem->value --;

local_intr_restore(intr_flag);

return 0;

}