zoukankan      html  css  js  c++  java
  • ucore-lab1-ex6

    完善中断初始化和处理

    1.中断描述符表(也可简称为保护模式下的中断向量表)中一个表项占多少字节?其中哪几位代表中断处理代码的入口?

    一个表项占8字节,根据 interrupt vector 在 IDT 中找到一个 interrupt gate,根据 gate 的 offset 加上根据 segment selector 在 GDT 中找到的 base 即可得到中断处理程序的入口。

    2.请编程完善 kern/trap/trap.c 中对中断向量表进行初始化的函数 idt_init。在 idt_init 函数中,依次对所有中断入口进行初始化。使用 mmu.h 中的 SETGATE 宏,填充 idt 数组内容。每个中断的入口由 tools/vectors.c 生成,使用 trap.c 中声明的 vectors 数组即可。

    /* idt_init - initialize IDT to each of the entry points in kern/trap/vectors.S */
    void
    idt_init(void) {
         /* LAB1 YOUR CODE : STEP 2 */
         /* (1) Where are the entry addrs of each Interrupt Service Routine (ISR)?
          *     All ISR's entry addrs are stored in __vectors. where is uintptr_t __vectors[] ?
          *     __vectors[] is in kern/trap/vector.S which is produced by tools/vector.c
          *     (try "make" command in lab1, then you will find vector.S in kern/trap DIR)
          *     You can use  "extern uintptr_t __vectors[];" to define this extern variable which will be used later.
          * (2) Now you should setup the entries of ISR in Interrupt Description Table (IDT).
          *     Can you see idt[256] in this file? Yes, it's IDT! you can use SETGATE macro to setup each item of IDT
          * (3) After setup the contents of IDT, you will let CPU know where is the IDT by using 'lidt' instruction.
          *     You don't know the meaning of this instruction? just google it! and check the libs/x86.h to know more.
          *     Notice: the argument of lidt is idt_pd. try to find it!
          */
        extern uintptr_t __vectors[];
        int i;
        for(i = 0 ; i < sizeof(idt) / sizeof(struct gatedesc) ; ++ i)
        {
            SETGATE(idt[i], 0, GD_KTEXT, __vectors[i], DPL_KERNEL);
        }
        SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);
        lidt(&idt_pd);
    }   
    

    需要注意的是一些宏的使用,比如 GD_KTEXT,它的实现在 memlayout.h 中,相当于用由 index 左移三位构造了一个 Kernel 代码段的段选择子。

    当然还存在一些问题,

    【注意】除了系统调用中断(T_SYSCALL)使用陷阱门描述符且权限为用户态权限以外,其它中断均使用特权级(DPL)为0的中断门描述符,权限为内核态权限;而 ucore 的应用程序处于特权级3,需要采用` int 0x80`指令操作(这种方式称为软中断,软件中断,Tra 中断,在 lab5 会碰到)来发出系统调用请求,并要能实现从特权级3到特权级0的转换,所以系统调用中断(T_SYSCALL)所对应的中断门描述符中的特权级(DPL)需要设置为3。

    这里我觉得指导书的意思是写SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);,但是答案里给的是SETGATE(idt[T_SWITCH_TOK], 0, GD_KTEXT, __vectors[T_SWITCH_TOK], DPL_USER);,这段代码应该是后面challenge的代码,但是SETGATE(idt[T_SYSCALL], 1, GD_KTEXT, __vectors[T_SYSCALL], DPL_USER);这段代码不见了还是有些费解。。。

    3.请编程完善 trap.c 中的中断处理函数 trap,在对时钟中断进行处理的部分填写 trap 函数中处理时钟中断的部分,使操作系统每遇到 100 次时钟中断后,调用 print_ticks 子程序,向屏幕上打印一行文字”100 ticks”。

    真的很简单hhh

    static void
    trap_dispatch(struct trapframe *tf) {
        char c;
    
        switch (tf->tf_trapno) {
        case IRQ_OFFSET + IRQ_TIMER:
            /* LAB1 YOUR CODE : STEP 3 */
            /* handle the timer interrupt */
            /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
             * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
             * (3) Too Simple? Yes, I think so!
             */
            ticks ++;
            if(ticks % TICK_NUM == 0) 
                print_ticks();
            break;
        case IRQ_OFFSET + IRQ_COM1:
            ......
    }
    

    最后的结果如下:

    注意:这里目前只能打印一堆100 ticks,剩下的部分需要在后面的 challenge 部分完成。指导书上说会响应键盘输入,不知道为啥我这里不行,在 lab1_result 里 make 也不行。

  • 相关阅读:
    使用对象-关系映射持久化数据
    Spring中使用JDBC
    无法正确解析FreeMarker视图
    使用Java配置SpringMVC
    面向切面的Spring
    高级装配
    爬虫简介与request模块
    列表存储本质以及索引为什么从0开始
    列表和字典操作的时间复杂度
    记录腾讯云中矿机病毒处理过程(重装系统了fu*k)
  • 原文地址:https://www.cnblogs.com/LuoboLiam/p/13584537.html
Copyright © 2011-2022 走看看