文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>head.S分析

head.S分析

时间:2006-11-08  来源:ooike

因为setup.S1最后的为一条转跳指令,跳到内核第一条指令并开始执行。指令中指向的是内存中的绝对地址,我们无法依此判断转跳到了head.S。但是我们可以通过Makefile简单的确定head.S位于内核的前端。
在arch/i386 的 Makefile 中定义了
HEAD := arch/i386/kernel/head.o

而在linux总的Makefile中由这样的语句
include arch/$(ARCH)/Makefile
说明HEAD定义在该文件中有效

然后由如下语句:

vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
$(ARCHIVES) \
$(FILESYSTEMS) \
$(DRIVERS) \
$(LIBS) -o vmlinux
$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( a \)' | sort > System.map

从这个依赖关系我们可以获得大量的信息

1>$(HEAD)即head.o的确第一个被连接到核心中

2>所有内核中支持的文件系统全部编译到$(FILESYSTEMS)即fs/filesystems.a中
所有内核中支持的网络协议全部编译到net.a中
所有内核中支持的SCSI驱动全部编译到scsi.a中
...................
原来内核也不过是一堆库文件和目标文件的集合罢了,有兴趣对内核减肥的同学,
可以好好比较一下看究竟是那个部分占用了空间。

3>System.map中包含了所有的内核输出的函数,我们在编写内核模块的时候
可以调用的系统函数大概就这些了。

好了,消除了心中的疑问,我们可以仔细分析head.s了。

Head.S分析

1 首先将ds,es,fs,gs指向系统数据段KERNEL_DS
KERNEL_DS 在asm/segment.h中定义,表示全局描述符表中
中的第三项。
注意:该此时生效的全局描述符表并不是在head.s中定义的
而仍然是在setup.S中定义的。

2 数据段全部清空。

3 setup_idt为一段子程序,将中断向量表全部指向ignore_int函数
该函数打印出:unknown interrupt
当然这样的中断处理函数什么也干不了。

4 察看数据线A20是否有效,否则循环等待。
地址线A20是x86的历史遗留问题,决定是否能访问1M以上内存。

5 拷贝启动参数到0x5000页的前半页,而将setup.s取出的bios参数
放到后半页。

6 检查CPU类型
@#$#%$^*@^?(^%#$%!#!@?谁知道干了什么?

7 初始化页表,只初始化最初几页。

1>将swapper_pg_dir(0x2000)和pg0(0x3000)清空
swapper_pg_dir作为整个系统的页目录

2>将pg0作为第一个页表,将其地址赋到swapper_pg_dir的第一个32
位字中。

3>同时将该页表项也赋给swapper_pg_dir的第3072个入口,表示虚拟地址
0xc0000000也指向pg0。

4>将pg0这个页表填满指向内存前4M

5>进入分页方式
注意:以前虽然在在保护模式但没有启用分页。

--------------------
| swapper_pg_dir | -----------
| |-------| pg0 |----------内存前4M
| | -----------
| |
--------------------
8 装入新的gdt和ldt表。

9 刷新段寄存器ds,es,fs,gs

10 使用系统堆栈,即预留的0x6000页面

11 执行start_kernel函数,这个函数是第一个C编制的
函数,内核又有了一个新的开始。1
相关阅读 更多 +
排行榜 更多 +
侠盗女孩

侠盗女孩

动作格斗 下载
终极竞速赛

终极竞速赛

动作格斗 下载
剥皮大师

剥皮大师

休闲益智 下载