Linux kernel 分析之三:加电BIOS启动

      Linux内核为什么不是从main函数开始执行?

      事实上,Linux内核源代码里有许多main()函数,但仔细一看。他们都是运行在用户态的。其实,从上一节中可以看到,main()函数只是一个符号而已。很多书上提到start_kernel()。它类似于main()。但正如调用main()的是_start()。在start_kernel之前仍然有很多代码。所以内核的真正入口并不是start_kernel()。
     真正决定程序执行入口的是载入程序。对普通的C程序helloworld来说,Linux内核(严格的说应该是bash)负责设置helloworld的入口点,并且启动helloworld进程的执行。
     于是,问题出现了,Linux内核的载入程序是什么呢?难道是自己载入自己?

     这类类似的问题在计算机史上出现过很多次,比如,C程序可以用C编译器来写,那么,C编译器用什么来写呢?当然,解决的方案有很多种,比如,用汇编语言写。那么汇编器用什么写呢?可以用机器语言写。虽然是件痛苦的事,但是一想到能造福这么多人,(发散一下,C编译器可以编译出各种新的语言的编译器或者解释器如perl,然后程序员们再用perl来编出各种复杂的系统),简直太伟大了,那位用机器语言写汇编器的程序员一定会浑身干劲。
    可以借鉴一下思路,这类问题的常见的解决方式是构造一个简单的系统来解决一个复杂的系统的问题,如此往复,像滚雪球一下,最终把一个极为复杂的问题解决掉。
所以,很自然的想到,用一个简单的内核,(不,它仅仅是一段程序,甚至不能称之为内核,因为它的功能很有限)来启动真正的内核。就像用一个小当量的原子弹来引爆氢弹一样。
    本着KISS(keep it simple and stupid)的原则,你第一时间可能会想到BIOS。BIOS通常存在ROM上。随着ROM容量的扩展(达1M甚至更多)PC上的BIOS功能已经很强大了,包括了很多设备的驱动程序。不仅可以进行硬件的检测,还实现了基本的输入输出功能。(basic input / output system,这也是它的本意)。开机时按del键出现的BIOS设置画面就是BIOS的杰作。在BIOS上实现一个OS也不是不可能。事实上DOS就是在BIOS的基础上实现的。
    然而,BIOS的一个致命的缺点是到目前为止它基本上只能在16位实地址模式下运行,毕竟ROM的容量很有限。(当然也不绝对,BIOS也提供了在保护模式下扫描PCI设备的方法,大牛们yy一下实现一个保护模式下运行的BIOS的可行性。)而CPU刚加电时处在16位实地址模式下。它的另一个致命的缺点是太小。因为现代操作系统多种多样,BIOS再强大也无法把所有可能的情况都考虑进去。
    不过即使这样,PC机刚启动时,x86 CPU仍然会自动从BIOS开始启动,这是由硬件决定的,因为加电时,寄存器CS里的值为0xffff,IP里的值为0。于是CPU从线性地址0xffff0处开始取指令。0xffff0处是什么地方呢?

运行cat /proc/iomem前面5行

00000000-0009fbff : System RAM

0009fc00-0009ffff : reserved
000a0000-000bffff : Video RAM area

000c0000-000cc7ff : Video ROM

000f0000-000fffff : System ROM


可以看到0xffff0处是System ROM,也就是BIOS注意这里的地址是16位实地址模式下的线性地址。而BIOS能做的事,包括开机时对设备的检测,最后去读硬盘上的第一个扇区(即引导扇区MBR)的512个字节,把它们拷贝到地址为0x7c00处的内存中。到此为止,BIOS的引导使命已经完成。虽然以后Linux内核的引导还要用到BIOS的功能,但引导的使命已经落在其它程序上了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值