作业地址
整个作业根据给出的 Hint 完成就行
创建 alarmtest.c 文件,添加代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#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 < 25 * 500000; i++) {
if ((i % 250000) == 0) write(2, ".", 1);
}
exit();
}
void periodic() { printf(1, "alarm!\n"); }
|
在 Makefile 中添加
在 user.h 内添加
1
|
int alarm(int ticks, void (*handler)());
|
在 syscall.h 中添加
在 usys.S 中添加
在 proc.h 中 proc
结构体内添加间隔和指向处理函数的指针
1
2
3
4
5
|
struct proc {
// ...
int alarmticks;
void (*alarmhandler)();
}
|
在 syscall.c 中添加相关系统调用 sys_alarm()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
int
sys_alarm(void)
{
int ticks;
void (*handler)();
if(argint(0, &ticks) < 0)
return -1;
if(argptr(1, (char**)&handler, 1) < 0)
return -1;
myproc()->alarmticks = ticks;
myproc()->alarmhandler = handler;
return 0;
}
|
在 syscall.c 中添加
1
2
3
4
5
6
|
extern int sys_alarm(void);
static int (*syscalls[])(void) = {
// ...
[SYS_alarm] sys_alarm,
}
|
在 proc.h 中添加计数器
1
2
3
4
|
struct proc {
// ...
int cntticks;
}
|
在 trap.c 中 trap()
内 T_IRQ0 + IRQ_TIMER
中添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
switch(tf->trapno){
case T_IRQ0 + IRQ_TIMER:
// ...
if (myproc() != 0 && (tf->cs & 3) == 3) { // 只让 alarm 系统调用在用户态运行
myproc()->cntticks++;
if (myproc()->cntticks == myproc()->alarmticks &&
tf->eip != (uint)myproc()->alarmhandler) {
myproc()->cntticks = 0;
// 当 alarmhandler 结束后,需要返回至引起 alarm 系统调用的代码处
// 在中断发生后处于 kernel mode 所以不会保存寄存器值,要手动保存
// 将 eip 压栈
tf->esp -= 4;
*((uint *)(tf->esp)) = tf->eip;
// 将 alarmhandler 复制给 eip
tf->eip = (uint)myproc()->alarmhandler;
}
}
lapiceoi();
break;
}
|