main函数之tvinit
1. 中断描述符
中断描述符表idt共有256个项目,每个条目8字节,根据每个条目的类型不同,共有3种不同的门描述符如下:
在xv6中的设置idt代码如下:
注意,这个idt中断描述符表示被所有的cpu共享的。从代码中可以看出,所有的IDT中断选择子的RPL都是0,这表示所有的中断都是在内核级别执行的。另外,IDT中的DPL可以理解成当使用此IDT项时,CPL的最低级别。
xv6中使用SETGATE设置idt表项,SETGATE的具体内容如下:
从图中可以看出,主要设置的就是门的类型、CS选择子、中断处理函数的地址(由于代码段的基址都设置的为0,所以偏移量就是实际代码所在的地址)、DPL等级。
idt表示xv6中的中断描述符表,共256项:
2. 中断向量表
vectors[i]是在vector.S中定义的,表示对应向量号的中断处理函数地址:
以vector0为例,vector0的符号地址如下:
可以看出,vector0就是0号中断向量的处理函数的地址,第一个push是压入空的cpu错误码,因为有的中断向量处理器会产生错误码,有的不会,为了保证这两种情况下,栈中的数据个数都是一样,对于没有cpu错误号产生的中断向量,压入一个0值假装是错误号:
比如8号中断是会产生cpu错误码的,所以只push了中断号:
第二个压入的是当前中断向量号,然后调用alltraps。alltraps定义在trapasm.S中:
首先压入其他的寄存器形成一个完整的中断帧,具体细节可见xv6-book第三章,然后设置内核的数据段寄存器,接着调用trap函数,trap函数的参数的中断帧地址,所以把esp压栈。当trap函数结束后,恢复栈指针。完整中断帧如下:
当中断函数处理完后,调用trapret:
trapret首先弹出一些寄存器,然后调整栈指针到保存eip值的地方,这样执行iret指令后,处理器就回返回到原来被打断的代码处继续执行。
3. 系统调用软中断
回到代码中,首先设置了默认的256个中断描述符,然后单独设置了系统调用中断T_SYSCALL,在xv6下,系统调用的中断号是64,系统调用中断描述符被设置为一条陷阱门,DPL设置为用户级别,这样就可以从用户空间调用int指令产生软中断了:
下面几个函数是跟文件系统相关的,在分析文件系统时在来分析:
评论