开始因为Bochs的配置总是出现问题,一个配置文件在别人的电脑上能用,但在自己的电脑上就没法用。在网上查找资料发现:bochs的配置文件和物理主机的硬件配置密切有关,并且还和bochs的安装路径有关。有的电脑可能要把newharddrivesupport:enabled=1注释掉;有的电脑可能要把
diskc:file=diskc.img, cyl=40, heads=8, spt=64
替换成ata0-master:type=disk,mode=flat,path=diskc.img,cylinders=40,heads=8,spt=64。
vgaromimage: /usr/share/bochs/VGABIOS-lgpl-latestromimage:file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000这两句中的路径要和bochs的安装路径相同,否则无法启动GeekOS。
在此文件夹中建立了一个新的文件d.c,然后进行make编译,运行Bochs,结果在命令解释器Shell下不能执行d.exe,查看/project2/build/user文件夹下没有出现d.exe,也就是说d.c并没有编译,这个问题出在makefile上,GeekOS默认的项目2的makefile文件中只是加入了b.c和c.c,所以后来的d.c并未参与编译,于是,在makefile中找到相应的位置把d.c加进去,然后编译、运行,Shell下g.exe成功运行。
在测试项目2时,当直接输入可执行文件的名称会出现“Failed to Read File xxx!”的错误提示,但最后程序还正常执行了。利用SourceInside跟踪程序的执行,发现process.c中的Spawn_With_Path首先尝试着调用Spawn_Program(最后通过DEF_SYSCALL调用sys_spawn,sys_spawn调用spwan来执行用户程序)执行程序,仅输入可执行文件的名称时spwan无法执行用户程序时间片不明显,于是出现了“Failed to Read File xxx!”的错误提示。通过Spawn_Program的返回值判断用户程序是否成功执行了,否则加上路径再次执行。
使用在其他文件中定义的变量要先用extern声明变量,否则编译不通过。在编写程序的时候可把全局变量的声明放在头文件中,其他源文件要使用这个变量包含对应的头文件即可,这样便于程序的维护。
在测试项目3的多队列优先级调度算法时经常遇到如下问题:
图1 项目3多队列优先级调度测试产生的错误
产生这个错误的原因是因为不可预期的中断,查阅相关资料发现:GeekOS中断调用的实现主要涉及到两个数据结构:中断描述符表s_IDT与中断处理函数表g_interruptTable.s_IDT在内核中静态分配,每个描述符指向lowlevel.asm文件中定义的中断向量宏定义程序段,这些程序段定义了256个中断向量的调用。其中,0~17号中断为Intel CPU的CPU中断向量,18~225号为用户自定义的中断向量。GeekOS将大多数中断处理函数初始化为函数Dummy_Interrupt_Handler,该函数在中断时显示当时保存的计算机各寄存器状态。12~13号CPU中断处理函数为GPF_Handler,系统调用使用Syscall_Handler中断处理函数,键盘,计时器等硬件中断也有各自的外部中断处理函数。
测试产生的中断是39号中断,GeekOS的中断处理函数是打印出相关的信息,然后终止系统执行,其实现如下:
static void Dummy_Interrupt_Handler(struct Interrupt_State* state)
{
Print("*** Unexpectedinterrupt! ***\n");
Dump_Interrupt_State(state);
STOP();
},我们注释这个函数的执行就可,也可自定义一个中断处理函数。
在实现信号量时也出现了13号中断的错误,导致程序直接被杀死,测试失败,如下图所示:
图2项目3信号量测试产生的错误
产生错误的原因直接在内核空间直接使用了用户空间的信号量名称,指针指向了错误的地址,导致产生页保护中断。使用Copy_User_String可将用户空间的数据复制到内核空间。此外还要特别注意字符串和指针的使用,字符串是一个字符数组,这一点要特别注意。