练习0
填写已有实验
本实验依赖实验1~实验6.请把已做的实验1~实验6的代码填入本实验中代码中有lab1、lab2、lab3、lab4、lab5、lab6的注释相应部分,并确保编译通过。
注意:为了能够正确执行lab7的测试应用程序,可能需对已完成的实验1~实验5的代码进一步改进
发现缺失的是kdebug.c、trap.c、default_pmm.c、pmm.c、swap_fifo.c、vmm.c、proc.c、sche.c
八个文件的相关代码,补全后不需要在6的基础上改了
练习1
理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题(不需要编码)
哲学家就餐问题
首先通过查阅资料,理解哲学家就餐问题
哲学家就餐问题,即有五个哲学家,他们的生活方式是交替地进行思考和进餐。哲学家们公用一张圆桌,周围放有五把椅子,每人坐一把。在圆桌上有五个碗和五根筷子,当一个哲学家思考时,他不与其他人交谈,饥饿时便试图取用其左、右最靠近他的筷子,但他可能一根都拿不到。只有在他拿到两根筷子时,方能进餐,进餐完后,放下筷子又继续思考。
筷子是临界资源,一段时间只允许一位哲学家使用。为了表示互斥,用一个信号量表示一只筷子,五个信号量构成信号量数组。本文中算法用类C语言描述伪码算法。算法描述如下:n用五支筷子的信号量构成信号量数组:
Semaphore chopstick[5]={
1,l,1,l,1};
Pi()
{
do
{
p(chopstick[i]);//取左边的筷子
p(chopstick[(i+1) % 5]);//取右边的筷子
eat; //进餐
v(chopstick[i]);//放回左边的筷子
v(chopstick[(i+1) % 5]);//放回右边的筷子
think;
}while(1);
}
思考:
当哲学家饥饿时,总是先去拿他左边的筷子,执行wait(chopstick[I])
,成功后,再去拿他右边的筷子,执行wait(chopstick[I+1]%5);
成功后便可进餐。进餐毕,先放下他左边的筷子,然后再放下右边的筷子。当五个哲学家同时去取他左边的筷子,每人拿到一只筷子且不释放,即五个哲学家只得无限等待下去,引起死锁。
这就很好的知道同步互斥问题很重要,然后分析下信号量。
在分析之前先对信号量进行简介,看书上关于Operating Systems Internals and Design Principles
第5章同步互斥
中对信号量实现的原理性描述:
struct semaphore {
int count;
queueType queue;
};
void semWait(semaphore s)
{
s.count--;
if (s.count < 0) {
/* place this process in s.queue */;
/* block this process */;
//入队,调度出去
}
}
void semSignal(semaphore s)
{
s.count++;
if (s.count<= 0) {
/* remove a process P from s.queue */;
/* place process P on ready list */;
//出队,放置准备列表
}
}
基于上诉信号量实现可以认为,当多个(>1)进程可以进行互斥或同步合作时,一个进程会由于无法满足信号量设置的某条件而在某一位置停止,直到它接收到一个特定的信号(表明条件满足了)。为了发信号,需要使用一个称作信号量的特殊变量。为通过信号量s传送信号,信号量的V操作采用进程可执行原语semSignal(s)
;为通过信号量s接收信号,信号量的P操作采用进程可执行原语semWait(s)
;如果相应的信号仍然没有发送,则进程被阻塞或睡眠,直到发送完为止。
ucore中信号量参照上述原理描述,建立在开关中断机制和wait queue
的基础上进行了具体实现。信号量的数据结构定义如下:
typedef struct {
int value; //信号量的当前值
wait_queue_t wait_queue; //信号量对应的等待队列
} semaphore_t;
接下来进入代码的分析。
lab7和之前的lab6的大体执行流程都与实验六相同,查看到proc.c
文件,发现init_main
中有问题
函数在开始执行调度之前多执行了一个check_sync
函数
check_sync函数
void check_sync(void){
int i;
//check semaphore
sem_init(&mutex,