GeekOS project2--自己做project2的流程遇到的问题及解决

来源:互联网 发布:mac无u盘安装win10 编辑:程序博客网 时间:2024/06/15 04:28

把project2的编译错误及bochs配置文件都弄好后,编译运行将会看到下面的结果


看到这个结果很奇怪,因为main.c中的Init_Timer();后面初始化没有运行,然后就有了“Switch to a new user address spac, if necessary”这句话。进入Init_Timer()发现调用Calibrate_Delay(),在Calibrate_Delay()中先关中断,后开中断,估计很有可能是中断这里有些道道不清楚。在 Enable_Interrupts();前后分别加上Print("Before Enable_Interrupts\n");Print("After Enable_Interrupts\n"); 重新make bochs启动会看到下面的结果。

我们添加在Enable_Interrupts();之前的打印语句打印出来了,后面的没有打印出来,这就说明了Enable_Interrupts();执行之后就发生了一次中断。发生中断后就跳转到打印“Switch to a new user address spac, if necessary”这句话的函数里面了。可是我们不知道它是怎么跳转进去的,只有一招了,那就是在源代码中搜索”Switch to a new user address spac, if necessary”这句话搜索的方法有很多种,比如在project2这个目录下用:
grep Switch\ to\ a\ new\ user\ address\ space . -Rn
这条命令,通过搜索发现这句话在由user.c里面的120行,是Switch_To_User_Context()这个函数打印出来的,继续搜索Switch_To_User_Context()这个函数,还是在project2这个目录下
grep Switch_To_User_Context  . -Rn
可以发现是lowlevel.asm这个汇编程序里面调用了Switch_To_User_Context()这个函数,打开lowlevel.asm可以发现Switch_To_User_Context()是在Activate_User_Context这个宏定义里面被调用,而Activate_User_Context这个宏在两个地方被使用,一个是Switch_To_Thread,另一个是Handle_Interrupt(这个是中断处理),结合上面开中断,可以推断是在Handle_Interrupt里面使用了宏Activate_User_Context,进而调用了Switch_To_User_Context()这个函数。

下面看看Switch_To_User_Context()具体要做写什么,注释里面写了要求调用Set_Kernel_Stack_Pointer() 和 Switch_To_Address_Space()这两个函数。
先看Set_Kernel_Stack_Pointer()函数,这个函数是在tss.c里面实现的,主要功能是保存当前函数的esp。从lowlevel.asm中
的宏Activate_User_Context可以看出Switch_To_User_Context()接收到了两个参数
(c语言中是后面参数先入栈),
%macro Activate_User_Context 0; If the new thread has a user context which is not the current; one, activate it.push    esp                     ; Interrupt_State pointerpush    dword [g_currentThread] ; Kernel_Thread pointercall    Switch_To_User_Contextadd     esp, 8                  ; clear 2 arguments%endmacro
所以把g_currentThread的esp传给Set_Kernel_Stack_Pointer(),Set_Kernel_Stack_Pointer(kthread->esp);

现在系统刚刚启动初始化还没未完成,还在内核态,所以现在调用这个Switch_To_User_Context()什么都不用做,只用返回一下。从书中我们知道判断一个线程是在内核态还是用户态只用判断kthread->userContext是否为空就行了。所以加代码:
if(kthread->userContext== NULL)
{
// Print("kthread = %x &&&\n", kthread);
return ;
}


改了之后就是这个结果。
(未完待续……)
原创粉丝点击