MIT6.828 HW5 CPU alarm
2016-05-30 20:58
471 查看
在这次练习中,我们将为xv6增加1个特性支持周期性发警告给进程。这对计算敏感的进程很有帮助,限制他们CPU的使用时间,也让进程在计算的同时执行一些周期性任务。更通用地来说,我们将实现1个用户级别的中断异常处理。在这里会用到上次系统调用的实现机制。
增加1个alarm(interval, handler)系统调用。当1个应用调用alarm(n, fn)时,那么每隔n个CPU时钟节拍,内核将使应用调用fn函数。当fn函数返回时,应用从调用处重新开始执行。
用户测试的用户程序:
期望的输出:(形式一致即可)
实现思路:
1、按照添加系统调用的方式添加用户态调用程序、系统调用号和系统调用程序
2、在proc.c的proc结构体中添加变量记录总ticks、当前ticks和对应的handler
challenge部分:
1、保存调用者的寄存器,当调用结束时恢复。由于调用的是无参数函数,故此只要保存EIP(返回地址)即可。
2、防止重叠进入handler函数,即handler未处理完不该再调用handler,具体可以通过再添加1个变量表示是否已经进入handler。
3、检查tf->esp的有效性,因为在调用handler时涉及对用户栈的操作,检查tf->esp所在页的有效性和权限。
至此,本次HW就到此了。
增加1个alarm(interval, handler)系统调用。当1个应用调用alarm(n, fn)时,那么每隔n个CPU时钟节拍,内核将使应用调用fn函数。当fn函数返回时,应用从调用处重新开始执行。
用户测试的用户程序:
#include "types.h" #include "stat.h" #include "user.h" void periodic(); int main(int argc, char *argv[]) { int i; printf(1, "alarmtest starting\n"); alarm(10, periodic); for(i = 0; i < 50*500000; i++){ if((i++ % 500000) == 0) write(2, ".", 1); } exit(); } void periodic() { printf(1, "alarm!\n"); }
期望的输出:(形式一致即可)
$ alarmtest alarmtest starting .....alarm! ....alarm! .....alarm! ......alarm! .....alarm! ....alarm! ....alarm! ......alarm! .....alarm! ...alarm! ...$
实现思路:
1、按照添加系统调用的方式添加用户态调用程序、系统调用号和系统调用程序
//user.h int alarm(int ticks, void(*hander)()); //usys.S SYSCALL(alarm) //Makefile UPROGS: _alarmtest\ //syscall.h #define SYS_alarm 23 //syscall.c extern int sys_alarm(void); //syscall.c syscalls[] [SYS_alarm] sys_alarm, //sysproc.c int sys_alarm(void) { int ticks; void (*handler)(); if(argint(0, &ticks) < 0) return -1; if(argptr(1, (char**)&handler, 1) < 0) return -1; proc->alarmticks = ticks; proc->alarmhandler = handler; return 0; }
2、在proc.c的proc结构体中添加变量记录总ticks、当前ticks和对应的handler
//struct proc int alarmticks; int curalarmticks; void (*alarmhander)();
3、在trap.c中处理时钟中断添加handler
case T_IRQ0 + IRQ_TIMER: if(cpu->id == 0){ acquire(&tickslock); ticks++; wakeup(&ticks); release(&tickslock); } if(proc && (tf->cs & a1f7 amp; 3) == 3){ proc->curalarmtick++; if(proc->alarmticks == proc->curalarmtick){ // 到达了周期 proc->curalarmtick = 0; //下面两句将eip压栈 tf->esp -= 4; *((uint *)(tf->esp)) = tf->eip; // 将alarmhandler复制给eip,准备执行 tf->eip =(uint) proc->alarmhandler; } } lapiceoi(); break;
challenge部分:
1、保存调用者的寄存器,当调用结束时恢复。由于调用的是无参数函数,故此只要保存EIP(返回地址)即可。
2、防止重叠进入handler函数,即handler未处理完不该再调用handler,具体可以通过再添加1个变量表示是否已经进入handler。
3、检查tf->esp的有效性,因为在调用handler时涉及对用户栈的操作,检查tf->esp所在页的有效性和权限。
至此,本次HW就到此了。
相关文章推荐
- PL/SQL数据开发那点事
- 构建之法阅读笔记04
- [RxJS] Filtering operators: throttle and throttleTime
- shell(五)
- 【Java】LRS最小重复子串
- wired unmanage ubuntu14.04
- 【CF675C】Money Transfers(离散化,贪心)
- 一篇学会自定义View
- 《校园封神榜》第二阶段个人工作总结——第七天
- bash 遍历目录下文件
- 安卓对象传递_二
- 径向基神经网络RBF
- UML之用例图
- jq过滤器方法 选择器
- Easy-题目57:28. Implement strStr()
- request.getParameter() 和request.getAttribute() 区别
- appserv - 最简单的绑定路径
- 用malloc动态申请一个二维数组的三种方法
- 正则大全
- 51nod 棋盘问题(博弈论)