要移植Linux首先得明白Linux的工作流程。下面描述下我理解的启动过程。
1:从Bios中读取硬件信息,开始自检,如果发现硬件错误,则报警。读取硬件参数时,可以读取到用户设定启动盘。
2:从启动盘的主引导分区(就是这个启动盘的第一个分区)读取该Linux 内核的启动引导程序(Boot Loader).执行引导程序。
3:引导程序从启动盘中读取内核,加载Linux 的内核(Kernel)到内存中, 并把控制权交给kernel.(通常是程序跳转到Kernel 的main 函数处).
4:Kernel执行,它先检测硬件并加载需要的驱动程序。
Linux内核的驱动程序是动态加载的。这些驱动程序是放在 /lib/modules 目录内。既然这些内核驱动程序都在根目录下,为了能正确取得驱动,内核也必须挂载到根目录下。现在假设内核是放在内核不认识的设备中,例如SATA硬盘,要驱动这个硬盘,需要加载它的驱动,但是驱动程序又在该硬盘的/lib/modules中,自然就无法得到,启动失败。
为了解决问题,使用了一种虚拟文件系统,名字为 /boot/initrd, 它通过bootloader 加载在内存中。这个文件被解压缩后,被仿真成个根目录。
Initrd 是将/lib/modules/.. 的启动过程中需要的驱动程序打包成一个文件,文件名就是initrd. 在内核中被解压缩后,仿真成根目录,内核就可以从中启动需要的驱动程序了.
如果内核驱动程序是放在内核认识的设备上,例如ide硬盘,就不需要initrd. 因为内核可以直接从设备上读取驱动程序.
5:硬件驱动正常后,kernel 调用/sbin/init 程序执行初始化启动任务..
初始化任务是根据配置文件执行的,/etc/inittab.
/etc/inittab 内容如下:
Id:5:initdefault: //系统上电默认运行的级别 5 级
Si::sysinit:/etc/rc.d/rc.sysinit // 指定系统初始化要执行的脚本文件 /etc/rc.d/rc.sysinit
0::wait:/etc/rc.d/rc 0 //level 0 的脚本放的地方 /etc/rc.d/rc0.d
1
..
7::wait:/etc/rc.d/rc 7
Ca::ctrlaltdel:/sbin/shutdown –t3 now //设定重启按键
1:2345:respawn:/sbin/mingetty tty1 //启动几个终端
..
6 ….. tty6
X:5:respawn:/etc/X11/prefdm –nodaemon //运行x window
Init 进程先取得默认运行级别,再执行 /etc/rc.d/rc.sysinit 脚本,初始化系统工作环境。
初始化包括取得网路环境,测试挂载内存/proc 和usb 设备/sys., 设定字体,显示欢迎界面,
设定时钟,加载用户自定义的模块驱动,等等…
初始化后,运行刚选的级别5 里面的服务程序。最后运行 x window ,等用户输入。