Orange's 一个操作系统的实现 第六章 阅读+实践
先贴代码地址 代码点我
完成工作如下:
- 读者写者问题的进程调度模拟
- 实现添加系统调用
代码流程 (可看作对原书内容的注解)
-
main.c
-
从main.c 开始,解释刚开始的几个变量:
global.c 里声明了task_table 这是main.c中需要执行的任务集合 ,比如TestA、TestB等;这里还有一个user_proc_table,它们的区别是什么呢?
task_table是操作系统要执行的任务的集合;而user_proc_table里装的是用户进程
代码里 我为了方便 把读者写者都写成了内核进程(但其实应该是用户进程)
-
下面很长的for循环:
进行进程队列的初始化,要结合process的结构来看,具体结构看书
作用:将TASK(内核进程)和PROCESS(用户进程),全部装到proc_table里,这里可能有一点疑惑,要分清楚user_proc_table和proc_table
-
在接下来一段初始化“ticks"和”priority“:
tick:该进程还能被分几个时间片(说是时间片,但其实它在我们实现的操作系统中并不是想象中的那样”10ms一个时间片“,而是”占用CPU的次数“)
priority:所有进程时间片都用完后,tick的初值要是多少?这里需要一个量来保存
-
然后就轮到”restart()"
这个函数是写在kernel.asm里的,作用有点像一个“隐式的函数调用”
在接下来就会执行“p_proc_ready"所指向的进程(TestA)
到这里就脱离了main,走向了进程调度
-
-
proc.c
这里需要有信号量和PV操作的知识背景
进程的切换操作都在schedule中完成
-
我们所有的读者写者进程都用到了”reader"方法或“writer”方法,而这两个方法中会有对信号量的PV操作,V操作不会调用schedule,P操作在信号量达到“被使用”(不知道怎么表达,意会一下)上限时,就会陷入”阻塞/等待态“,并调用schedule触发进程切换
PROCESS结构体中加入了wait作为等待态的标志位
-
schedule中实现进程切换的原理:轮询判断proc_table中的进程是否为阻塞态或是否正在”休眠“(休眠时间由PROCESS中的sleep_time表示)
-
-
系统调用的实现:
-
syscall.asm中定义了系统调用的入口(写完函数,记得要导出)
-
kernel.asm中定义了一个sys_call函数,它会根据eax中的值,决定调用sys_call_table(global.c中定义)中的哪个系统调用函数
-
由于我们实现的系统调用要有传参,结合C和asm传参约定,要对ebx中的值进行保存
-
-
总结:
- TestA、B、C调用reader和writer
- reader和writer调用do_p/do_v/do_sleep
- do_p、do_v、do_sleep以调用sys_p/sys_v/sys_sleep
- sys_p和sys_sleep调用schedule进行进程调度