一个小的OS内核,一些感受,一些总结。

来源:互联网 发布:mac系统excel下拉菜单 编辑:程序博客网 时间:2024/05/29 02:47
 
前几天刚读了《Bran的内核开发指南》,感觉有些收获。这里简单总结一下。
可以从http://rammaker.cosoft.org.cn/store/bkerndev_zh_CN_beta/index.htm得到完整的文档。
首先介绍下我的环境:
DJGPP,NASM [Windows]
VMWare WorkStation.(上跑RedHat Linux)
在将一个编译好的简单kernel运行的时候,用的是VMWare上虚拟的软盘。至于怎样在软盘上装grub等,不提。
下面说下几点体会:
1.对于一个整个系统,或者叫一个整个的工程,一般都是有若干个小的部分组成的。以这个kernel为例,为了生成最终的一个kernel.bin,需要编写若干个.c文件和一个.asm文件。在分别将这些文件编译成.o后,最终需要一个ld的过程。从最终文件来看,这些各组成文件中的符号应该是全局惟一的,因为他们最终都会在kernel.bin中存在。以前在学习c的时候,讲到关键字extern,说它的作用是声明一个变量或者函数在另外一个模块中定义,现在终于体会到了是怎么一回事。也从全局的角度来看,对于.bin的贡献(^_^).asm.c是相同的。只是.asm只需一个nasm,而.c需要预处理,编译,汇编的过程而已。
2.在过程中,曾遇到这样一个问题:我在DJGPPgcc了那些.c文件,但是我却在RH Linux中用ld,结果总是出现某些符号为定义的错误。找过去,找过来,最终发现一个问题。在DJGPPGCC生成的文件是COFF格式,而RH LINUX下的LD需要的是ELF格式。我猜测,因为格式的不同,ELF格式中对于.C的函数和变量符号在汇编后,在.S中是用本身的符号表示的,而不做变换。如.C中有函数ABC(),在编译后的.S中也以符号ABC表示;而COFF格式中对于.C的函数和变量符号在汇编后,在.S中会对他们的符号作些变换,具体是在前面加一个下画线。例如:.C中的函数ABC()在编译后的.S中会以符号_ABC表示。所以,当我换在WINDOWS CMD下,用LD链接后,没有出现问题。这时用的LD应该就是以COFF格式输入的。
3.在生成了KERNEL.BIN后,COPY到软盘下时,要注意:BOOT/GRUB下面的STAGE1,2的访问权限要有X(试试知道的)
4.在汇编和C间传递参数用栈就可以了。并且,可以定义结构来表示栈中的内容,但要主要栈中内容的顺序和结构的顺序。
对于OS内核,有些感受:
5.正如MULTIBOOT规范中所讲,一个OS的内核的格式应该可以是操作系统中可以运行的文件的格式,入A.OUTELF等。为了能够引导不同格式的内核,也及可以利用MULTIBOOT,那么就必须在内核文件的开头或者某些特殊位置定义某些固定的变量。如MAGIC等。
6.接上,既然内核可以是一般格式的可执行文件。那么它就可以象应用程序那样使用系统的内存,该文件也可以定义若干的数据结构。只是,为了满足硬件对于操作系统的支持,需要把这些数据结构的地址,大小等加载到某些特定功能的寄存器。GDT的地址和大小限制需要一个数据结构来表示,该结构的地址需要被LOADGDTR中,类似的还有IDTIDTR.
7.IDT中保存了若干的中断号以及中断服务程序的地址后,也可以对它们的映射关系做改变。当然,对于开始的32个中断(异常)是保留的,后面的可以自己映射。对于这里,以前一直不是很理解,现在简单总结一下中断。当一个中断源(如键盘,系统时钟)到来时,在8259对它们进行优先级判断等操作后通知CPUCPU在得到它们的中断号后,通过IDTR得到IDT的基地址,然后用中断号取出距离IDT若干距离的ISR的地址,并转到该ISR运行。注意,这个IDTR是我们用指令LIDT写入的。其实,从这个KERNEL来看,我们就只需加载GDTRIDTR,以及提供一些映射就可以了。其他的,CPU会在遇到某种情况时自己找到该运行的程序。

 上面的东西,部分是我自己猜测的,希望各位看官能够指出其中的错误。感谢万分。

原创粉丝点击