recc项目中设计的OS完成了整体操作系统框架的构建,包括中断处理,二级页表映射,进程调度,以及串口读写。
我们对这一OS进行了精简,删除了其中的页表映射和文件系统部分。此外,还进行了一些移植工作,包括修改其中不符合标准C语言规范的语句、重写汇编文件、移除除法指令等。
系统运行的入口为OS2018spring-projects-g02/recc-kernel-llvm/kernel/l2/entry.s
中的main
函数,该过程进行简单的堆栈初始化后,跳转到kernel\_impl.c
中的k\_kernel\_init
开始执行。该函数会初始化各进程,设置其堆栈,最终打开所有中断使能并开始进程调度。
系统的中断处理入口在kernel\_impl.c
中的k\_irq\_handler
开始执行。其并不对中断进行任何处理,只是简单的重置中断位,然后唤醒等待相应中断的进程进行处理并运行进程调度器。因此,系统中所有中断的处理都是由相应进程完成的。
OS中共有8个进程同时工作,其编号、名称及用途如下:
- init,系统内核进程
- user_proc_1,输出进入操作系统时的欢迎信息。
- clock_tick_counter,每次触发时钟中断时记录触发次数。
- uart1_out_ready_notifier,等待串口输出完成信号。当串口输出中断触发时,该进程会捕捉这一中断,并将当前字符输出完毕的信息发送给uart1_out_server。
- uart1_out_server,串口输出控制器。它负责接收其他进程(user_proc_1或command_server)的输出请求,并将需要输出的字符排列为一个队列。当收到uart1_out_ready_notifier发送的信号时,它会将队列中下一个字符通过串口发送。
- uart1_in_ready_notifier,等待串口输入完成信号。当串口输入中断触发时,该进程会捕捉这一中断,并将有一个字符输入完毕的信息发送给uart1_in_server。
- uart1_in_server,串口输入控制器。它负责接收串口输入,并将其转发到其他进程(command_server)。当收到uart1_in_ready_notifier发送的信号时,它会将串口中的字符读入并转发。
- command_server,一个终端,用于接收串口发来的控制命令,之后打印相应信息到串口。
OS中实现的是非常简单的最高优先权优先算法(FPF)。简单来说,它将所有进程分为4个优先级,每次需要进程调度时,它会依次检查优先级为0、1、2、3的进程,试图找到一个进程跳转执行。
OS中进程之间的信息传递是通过进程消息实现的。一个进程消息的传递过程如下:
- 源进程向操作系统申请发送进程消息
- 操作系统将源进程挂起,并检查目标进程状态:
- 如果目标进程因为等待接收进程消息被挂起,则将目标进程唤醒
- 否则将消息置入目标进程的消息队列
- 目标进程向操作系统申请接收进程消息
- 操作系统检查目标进程状态:
- 如果目标进程的消息队列中有消息在等待,则返回队列中第一个消息
- 否则将目标进程挂起
- 目标进程接收到进程消息后进行处理,并向操作系统申请反馈结果
- 操作系统将反馈结果发送给源进程,并唤醒源进程