码迷,mamicode.com
首页 > 其他好文 > 详细

MIT 6.828 JOS/XV6 LAB4-partC

时间:2016-01-06 15:40:22      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:

这一部分要实现抢占式调度和进程间通信

前面的调度是进程资源放弃CPU,但是实际中没有进程会这样做的,而为了不让某一进程耗尽CPU资源,需要抢占式调度,也就需要硬件定时

但是外部硬件定时在Bootloader的时候就关闭了,至今都没有开启

而JOS采取的策略是,在内核中的时候,外部中断是始终关闭的,而在用户态的时候,需要开启中断

所以首先需要求改IDT,但是我在之前把256个都弄好了

所以现在只需要在进入用户态的时候,保证外部中断是使能的就可以了,为了做到这一点,可以在每个进程初始化的时候就将外部中断使能位置位

在kern/env.c的env_alloc中

技术分享

现在虽然中断使能已经打开,在用户态进程运行的时候,外部中断会产生并进入内核,但是现在还没有能处理这类中断

所以需要修改trap_dispatch,在发生外部定时中断的时候,调用调度器,调度另外一个可运行的进程

技术分享

在跑make run-spin的时候,总是遇到bug,发现父进程调用sys_env_destroy没能把子进程杀死

找了半天,发现传入sys_env_destroy的参数是子进程的进程id,而在内核的系统调用sys_env_destroy中,却莫名其妙的变成了父进程的进程id,最后发现是syscall函数写错了

技术分享

这一句的参数应该是a1,我却写成了curenv->env_id

这个问题显然是自lab3就有的,但是到现在才发现是错的,而且之前一直没有出错。。。

实现IPC

IPC是计算机系统中非常重要的一部分,而JOS选择了一种看起来挺别扭的方法来实现

两个进程需要通信的话,一方要发起recv,然后阻塞,直到有一个进程调用send向正在接受的进程发送了信息,阻塞的进程才会被唤醒

而JOS中,可以允许传递两种信息,一是一个32位整数,另外一个就是传递页的映射,在这个过程中,接收方和发送方将同时映射到一个相同的物理页,此时也就实现了内存共享

然后将这两个功能实现在了同一个系统调用中

首先看内核中的sys_ipc_recv函数。当一个进程试图去接收信息的时候,应该将自己标记为正在接收信息,而且为了不浪费CPU资源,应该同时标记自己为ENV_NOT_RUNNABLE,只有当有进程向自己发了信息之后,才会重新恢复可运行

技术分享

将自己标记为不可运行之后,调用调度器运行其他进程

而内核中的sys_ipc_try_send的实现则相对来说麻烦很多,因为有很多的检测项,包括权限是否符合要求,要传送的页有没有,能不能将这一页映射到对方页表中去等等

技术分享

如果srcva是在UTOP之下,那么说明是要共享内存,那就首先要在发送方的页表中找到srcva对应的页表项,然后在接收方给定的虚地址处插入这个页表项

接收完成之后,重新将当前进程设置为可运行,同时把env_ipc_recving设置为0,以防止其他的进程再发送,覆盖掉当前的内容

以上的两个函数都是系统调用,而在用户态下的函数调用需要另外实现

技术分享

技术分享

至此,整个lab4就实现完成了,好累。。。

MIT 6.828 JOS/XV6 LAB4-partC

标签:

原文地址:http://www.cnblogs.com/bdhmwz/p/5105352.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!