interrupt.c

pintos中的中断有256个即0-255. void *frame_pointer; 是一个frame总会有个指针 void (*eip) (void); 下一个执行的指令的地址。 void *esp; stack pointer 栈指针 IDT(Interrupt Descriptor Table)是一个描述interrupt的数组,即idt[INTR_CNT]; PIC(可编程中断控制器):外设发出中断请求需要PIC进行处理。 当发生中断时先调用intrNN_stub();这是用汇编写的。接着调用intr_entry();即把intr_frame放入栈中。最后调用intr_handler()执行特定注册过的中断。 intr_handler();返回后则恢复现场,即把栈中的CPU寄存器的值都恢复。 intr_frame里面的都是CPU寄存器的值,我们在中断时所要做的事就是保存现场,而这就是一个现场,我们只要把这个放入栈中即可。 static intr_handler_func *intr_handlers[INTR_CNT];这个就是对应每个中断处理函数。 static unsigned int unexpected_cnt[INTR_CNT];这个是记录了每个中断里没有注册中断处理函数的计数。 static bool yield_on_return;一般外部中断是不能yield或sleep。 intr_init() 函数把中断的一些基本配置都配好了。0-19都是有原因的中断,20以上就是unknown。 //------------------------------------------------------------------------------------------------------------------------------------------- static void register_handler (uint8_t vec_no, int dpl, enum intr_level level, intr_handler_func *handler, const char *name) { ASSERT (intr_handlers[vec_no] == NULL); if (level == INTR_ON) idt[vec_no] = make_trap_gate (intr_stubs[vec_no], dpl); else idt[vec_no] = make_intr_gate (intr_stubs[vec_no], dpl); intr_handlers[vec_no] = handler; intr_names[vec_no] = name; } 这个函数的意思是vec_no的中断调用了这个函数,调用handler这个函数的前提是vec_no的中断执行程序还没有被注册。 这样这个函数就可以把handler注册为中断处理程序,dpl(descriptor privilege level)只有两种取值,第一种为3,意思是允许用户模式中断,第二种0,意思是禁止中断。 如果level是打开中断,则把idt[vec_no]描述为make_trap_gate.并且把intr_handler[vec_no]赋值,name也赋值。 void intr_register_ext (uint8_t vec_no, intr_handler_func *handler, const char *name) { ASSERT (vec_no >= 0x20 && vec_no <= 0x2f); register_handler (vec_no, 0, INTR_OFF, handler, name); } 这个函数的作用是注册外部中断的处理函数,因此dpl=0,因为外部中断必须是设备发出的信号,因此不可能是用户进程调用的,INTR_OFF说明处理函数时不能中断。 static uint64_t make_gate (void (*function) (void), int dpl, int type) type有两种取值,第一种14,意思是进入中断并且禁止中断,第二种15,意思是进入中断开启中断。这个函数的目的是为了打开一扇门能调用handler。 static uint64_t make_intr_gate (void (*function) (void), int dpl) { return make_gate (function, dpl, 14); } 因此interrupt gate是禁止中断,所以type是14. static uint64_t make_trap_gate (void (*function) (void), int dpl) { return make_gate (function, dpl, 15); } 这里为15.开启中断。 void intr_register_ext (uint8_t vec_no, intr_handler_func *handler, const char *name) { ASSERT (vec_no >= 0x20 && vec_no <= 0x2f); register_handler (vec_no, 0, INTR_OFF, handler, name); } 是注册外部中断的程序,因此把dpl设为0,即禁止中断,外部中断执行程序是不能嵌套的。 //--------------------------------------------------------------------------------------------- bool intr_context (void) { return in_external_intr; } 看他是不是还在外部中断期间。 //---------------------------------------------------------------------------------------------- void intr_handler (struct intr_frame *frame) { bool external; intr_handler_func *handler; /* External interrupts are special. We only handle one at a time (so interrupts must be off) and they need to be acknowledged on the PIC (see below). An external interrupt handler cannot sleep. */ external = frame->vec_no >= 0x20 && frame->vec_no < 0x30; //看他是不是外部中断。因为外部中断只能一次执行一次。 if (external) { ASSERT (intr_get_level () == INTR_OFF); ASSERT (!intr_context ()); in_external_intr = true; //外部中断刚开始需要说明正在外部中断 yield_on_return = false; //并且不能在返回时yield } /* Invoke the interrupt's handler. */ handler = intr_handlers[frame->vec_no]; //内部中断只需执行这个handler即可。 if (handler != NULL) handler (frame); else if (frame->vec_no == 0x27 || frame->vec_no == 0x2f) { /* There is no handler, but this interrupt can trigger spuriously due to a hardware fault or hardware race condition. Ignore it. */ } else unexpected_interrupt (frame); //没有注册handler /* Complete the processing of an external interrupt. */ if (external) { ASSERT (intr_get_level () == INTR_OFF); ASSERT (intr_context ()); in_external_intr = false; //退出外部中断 pic_end_of_interrupt (frame->vec_no); //设置pic if (yield_on_return) //外部中断一定不会执行这句话 thread_yield (); } } //------------------------------------------------------------------- static void unexpected_interrupt (const struct intr_frame *f) { /* Count the number so far. */ unsigned int n = ++unexpected_cnt[f->vec_no]; /* If the number is a power of 2, print a message. This rate limiting means that we get information about an uncommon unexpected interrupt the first time and fairly often after that, but one that occurs many times will not overwhelm the console. */ if ((n & (n - 1)) == 0) printf ("Unexpected interrupt %#04x (%s)/n", f->vec_no, intr_names[f->vec_no]); } 这个函数只是把frame中对应的vec_no的unexpected_cnt数组加一。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值