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;
}
发布评论