关闭

MIT6.828 HW5 CPU alarm

626人阅读 评论(0) 收藏 举报
分类:

  在这次练习中,我们将为xv6增加1个特性支持周期性发警告给进程。这对计算敏感的进程很有帮助,限制他们CPU的使用时间,也让进程在计算的同时执行一些周期性任务。更通用地来说,我们将实现1个用户级别的中断异常处理。在这里会用到上次系统调用的实现机制。
  增加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 & 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就到此了。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:24884次
    • 积分:494
    • 等级:
    • 排名:千里之外
    • 原创:21篇
    • 转载:9篇
    • 译文:0篇
    • 评论:8条
    文章分类
    最新评论