实验目的
- 理解操作系统的同步互斥的设计实现;
- 理解底层支撑技术:禁用中断、定时器、等待队列;
- 在ucore中理解信号量(semaphore)机制的具体实现;
- 理解管程机制,在ucore内核中增加基于管程(monitor)的条件变量(condition variable)的支持;
- 了解经典进程同步问题,并能使用同步机制解决进程同步问题。
实验内容
练习0:填写已有实验
本实验依赖实验1/2/3/4/5/6。请把你做的实验1/2/3/4/5/6的代码填入本实验中代码中有“LAB1”/“LAB2”/“LAB3”/“LAB4”/“LAB5”/“LAB6”的注释相应部分。并确保编译通过。注意:为了能够正确执行lab7的测试应用程序,可能需对已完成的实验1/2/3/4/5/6的代码进行进一步改进。
要修改的文件有proc.c default_pmm.c pmm.c swap_fifo.c vmm.c trap.c kdebug.c
并将lab6的default_sched_stride.c
复制到lab7,并对default_sched.h sched.c
做修改
无需要在原代码基础上做进一步修改的代码
其中有个比较坑的地方需要做修改
此处需要和lab6一样改为MAX_TIME_SLICE
而且,比较奇怪的是,这个MAX_TIME_SLICE的值有时候能通过priority测验,有时候却不行,如果不行的话,可以将sched.h
的MAX_TIME_SLICE的值进行调节(例如把20改成5)看是否能通过测验。
修改后执行make grade
测试均通过
练习1: 理解内核级信号量的实现和基于内核级信号量的哲学家就餐问题
完成练习0后,建议大家比较一下(可用meld等文件diff比较软件)个人完成的lab6和练习0完成后的刚修改的lab7之间的区别,分析了解lab7采用信号量的执行过程。执行make grade
,大部分测试用例应该通过。
请在实验报告中给出内核级信号量的设计描述,并说明其大致执行流程。
请在实验报告中给出给用户态进程/线程提供信号量机制的设计方案,并比较说明给内核级提供信号量机制的异同。
请在实验报告中给出内核级信号量的设计描述,并说明其大致执行流程。
本次实验的底层支撑
信号量原理
信号量结构体包括信号量计数值sem和等待队列q
查看sem.c的头文件
查看文件kern/process/proc.c
可以看到在进程中,调用check_sync这个函数来解决哲学家问题
分析check_sync函数
1 | kern/sync/check_sync.c |
前半段是用信号量的方法,后半段是用管程的方法
pid用kernel_thread创建了一个内核线程,
其定义在kern/process/proc.c
其中fn表示内核线程执行的函数,arg表示传入的哲学家编号i,clone_flag表示共享内存的标志位
此处传入的函数为philosopher_using_semaphore
,查看这个函数定义
1 | kern/sync/check_sync.c |
传入参数*arg是哲学家的编号。
iter++<TIMES,表示循环4次,目的在于模拟多次试验情况。
其中用do_sleep这个延时函数来模拟哲学家的思考和进餐的过程,且睡眠过程是无法打断的。
另外还有phi_take_forks_sema(i)和phi_put_forks_sema(i)这两个函数,表示拿起叉子和放下叉子。
1 |
|
其中mutex是二进制信号量结构体。
down代表P操作,up代表V操作
打开sem.c,sem.h,wait.h
有如下定义
1 | // 先是定义了一个信号量的数据结构 |
整个执行过程如下
请在实验报告中给出给用户态进程/线程提供信号量机制的设计方案,并比较说明给内核级提供信号量机制的异同。
由于是用户态进程,不可以直接使用内核态的信号量,因此应该将内核级的信号量操作封装成系统调用供用户态调用。
异同点:
- 相同点:
- 提供信号量机制的代码实现逻辑是相同的;
- 不同点:
- 由于实现原子操作的中断禁用、Test and Set指令等均需要在内核态下运行,因此提供给用户态进程的信号量机制是通过系统调用来实现的,而内核级线程只需要直接调用相应的函数就可以了
练习2: 完成内核级条件变量和基于内核级条件变量的哲学家就餐问题
首先掌握管程机制,然后基于信号量实现完成条件变量实现,然后用管程机制实现哲学家就餐问题的解决方案(基于条件变量)。
执行:make grade
。如果所显示的应用程序检测都输出ok,则基本正确。如果只是某程序过不去,比如matrix.c,则可执行
1 | make run-matrix |
命令来单独调试它。大致执行结果可看附录。
请在实验报告中给出内核级条件变量的设计描述,并说明其大致执行流程。
请在实验报告中给出给用户态进程/线程提供条件变量机制的设计方案,并比较说明给内核级提供条件变量机制的异同。
请在实验报告中回答:能否不用基于信号量机制来完成条件变量?如果不能,请给出理由,如果能,请给出设计说明和具体实现。
该练习需要编程,查看需要编程的地方
这边写错了练习序号
管程实现机制
管程机制在monitor.c实现
1 | // 管程数据结构 |
补充check_sync.c的代码
1 | check_sync.c: |
具体原理如下
1 | 哲学家->试试拿刀叉->能拿->signal 唤醒被wait阻塞的进程->阻塞本身 |
make grade
通过
make run-matrix
有关输出显示
请在实验报告中给出给用户态进程/线程提供条件变量机制的设计方案,并比较说明给内核级提供条件变量机制的异同。
同练习1,通过系统调用实现
异同点类似
- 相同点:基本的实现逻辑相同;
- 不一样点:最终在用户态下实现管程和条件变量机制,须要使用到操做系统使用系统调用提供必定的支持; 而在内核态下实现条件变量是不需要的;
实验总结
本次实验是基于哲学家就餐问题所展开的,并分别用信号量机制和管程机制实现同步和互斥,本次实验代码较为复杂,但是所要编码的部分较为简单,其中管程部分较难理解,还是要多加学习。