分类: LINUX
2013-05-26 00:05:04
用了很长时间来平复自己浮躁的情绪。觉得自己应该做些什么,又不知道该如何去做。所谓万变不离其宗,知识的积累与沉淀。总是有些道理的。索性,定下心来,研究下Linux内核。图书馆环境很好,资源很丰富。只是这点,就让自己无理由不去好好做了。^^
大方向定了后,还是蛮踌躇满志的,一副信誓旦旦样子。这样也好。继而发现,自己操作系统的基础知识,竟也是不牢固的。浮沙筑高台,塌陷不自知。又不得不回顾下操作系统原理知识。后来,丰富的图书资源,竟成了一种禁锢。不知道从何处着手了。先后看了《linux内核修炼之道》(任桥伟著),《Linux内核设计与实现(原书第3版)》(陈莉君译)(ps:喜欢华章科技关于国外著名教材的出版,或许,只是单纯喜欢严谨又不失活泼的封面罢了,希望自己在以后,能发现更多精彩实质性的东西^^),前者多注重内核代码实现,后者又多注重理论基础。都是很不错的书,无奈自己不能定心。最后决定,使用《Linux内核设计的艺术》(新设计团队,基于Linux 0.11)为主,其他书籍以及网络为辅。既然要做了,那就做好了。
初始时候,被书中以图示方式演示内存状态的新设计打动了。感觉着,那些代码,终于在我的脑袋里流动了起来。^^然而,在第二章时候,发现有些磕磕绊绊了。相信Linux内核是趣味的,但在遇到困难时候,一些负面情绪就占上风了,自己能不能做到?学内核有用吗?。于是不得不说服自己,Linux内核是庞然大物的,又怎是我这小小小初学者一来二去就能掌握的了的。一回生,二回熟,坚持下去就好了。加上自己的学习方式,总是容易陷在磕绊处,如此,容易陷入只见树木不见森林的误区。终于决定,采取纵观全局,然后逐步细化的策略。
对自己所学知识,能够时常做下系统性的总结,我认为是个不错的方式,所以,希望自己能够坚持。记录下来自己学习Linux内核的点点滴滴。一来,可以鞭策自己,不要懈怠。二来,也可以对自己做下正面暗示,每天有所学就好。
对于没有项目经验又不知何处着手的我来说,Linux 0.11内核无疑是个比较合适的选择。希望能够通过这个过程,达到下述目标:
1.熟悉大型软件的概念,培养如何着手大型软件的能力和心态。
2.Linux 0.11内核是程序设计天才的天才作品,学习它们,巩固自己的C语言知识,也可以学习作者的设计思路与技巧。有益无害。
在此,先对之前的知识点做下简单回顾。(我希望,能把事情做的尽量完整)
第一章 开机启动到main函数执行之前过程
1.启动BIOS
计算机运行离不开程序,但只能运行存储在计算机内存(RAM)中的程序。然而在加电瞬间,RAM中什么都没有。BIOS程序被固化在计算机主板上的一块很小的ROM芯片中,它要做的工作就是将软盘中的操作系统程序加载到内存(RAM)中。这个动作自然由硬件完成。
Intel80x86系列CPU硬件设计加电即进入16位实模式状态运行,并在加电瞬间将CS值置为0xFFFF,IP的值置为0x0000,CS:IP就指向0xFFFF0位置,即BIOS地址范围(统一编址)。
BIOS程序在内存最开始位置(0x00000)构建中断向量表(0x00000~0x003FF),BIOS数据区(0x00400~0x004FF),中断服务程序(0x0E2CE~0x0FFFF)
中断向量表中有256个中断向量,每个中断向量占4个字节,CS和IP值各占2个字节。每个中断向量都指向一个具体的中断服务程序,后续程序就是利用这些中断服务程序把系统内核程序从软盘加载至内存。
2.从启动盘加载操作系统到内存
对于Linux 0.11操作系统而言,计算机将分三批逐次加载操作系统代码。
2.1 由BIOS中断int 0x19把第一扇区bootsect(引导程序)的内容加载到内存(内存中首次操作系统自己的代码);
2.2在bootsect作用下(bootsect.s),使用BIOS提供的int0x13中断,加载setup.s和system模块。
setup程序开始执行,首先利用BIOS提供的中断服务程序从设备上提取内核运行所需的机器系统数据(其中包括光标位置和显示页面数据),并分别从中断向量0x41和0x46向量值所指的内存地址获取硬盘参数表1和硬盘参数表2,把它们存放在0x9000:0x0080和0x9000:0x0090。
3.为保护模式和分页模式下main函数的执行做准备。
//boot/setup.s
3.1 关中断并将system模块移动到内存地址起始位置0x00000
3.2 设置中断描述符和全局描述符
3.3 setup(sectup.s)执行完毕,它为系统能够在保护模式下运行做了一系列准备工作。后续准备工作将由head.s完成。
//boot/head.s
head程序与bootsect和setup加载方式有所不同。先将head.s汇编成目标代码,C语言编写的内核程序编译成目标代码,然后链接成system模块。head程序在前,内核程序在后。故名head.head程序除了做些调用main准备工作之外,用程序自身的代码在程序自身所在内存空间创建了内核分页机制,即在0x000000的位置创建了页目录表,页表,缓冲区,GDT,IDT,并将head程序已经执行过的代码所占内存空间覆盖,意味着head程序废弃自身,main函数即将开始执行。