Linux 启动过程详解

Linux 启动过程详解
在了解了Linux 的常见命令之后,下面来详细了解一下Linux 的启动过程。Linux 的启动
过程包含了Linux 工作原理的精髓,而且在嵌入式的开发过程也非常需要这方面知识的积累。
为了降低阅读的难度,在这部分作者尽量避免直接对大段的汇编代码进行分析,而主要阐述
其原理及INIT进程。希望读者能认真耐心阅读,相信在真正掌握这一节的内容之后对Linux
的认识会有一个质的飞跃。
2.2.1 概述
用户开机启动Linux 过程总体上是这样的:
首先当用户打开PC 的电源时,CPU 将自动进入实模式,并从地址0xFFFF0 开始自
动执行程序代码,这个地址通常是ROM-BIOS 中的地址。这时BIOS 进行开机自检,并
按BIOS 中设置的启动设备(通常是硬盘)进行启动,接着启动设备上安装的引导程序
lilo 或grub 开始引导Linux(也就是启动设备的第一个扇区),这时,Linux 才获得了启
动权。
接下来的第二阶段,Linux 首先进行内核的引导,主要完成磁盘引导、读取机器系统数
据、实模式和保护模式的切换、加载数据段寄存器以及重置中断描述符表等。第三阶段执行init程序(也就是系统初始化工作),init 程序调用了rc.sysinit和rc等程序,
而rc.sysinit和rc在完成系统初始化和运行服务的任务后,返回init。
之后的第四阶段,init启动mingetty,打开终端供用户登录系统,用户登录成功后进入了
Shell,这样就完成了从开机到登录的整个启动过程。
Linux 启动总体流程图如图2.2所示,其中的4 个阶段分别由同步棒隔开。由于第一阶段
不涉及Linux 自身的启动过程,因此,下面分别对第二和第三阶段进行详细讲解。

2.2.2 内核引导阶段
在 grub 或lilo 等引导程序成功完成引导Linux 系统的任务后,Linux 就从它们手中接管
了CPU的控制权。用户可以从www.kernel.org上下载最新版本的源码进行阅读,其目录为:
linux-2.6.*.*\arch\i386\boot。在这过程中主要用到该目录下的这几个文件:bootsect.S、setup.S
以及compressed目录下的head.S等。
首先要介绍一下,Linux 的内核通常是压缩过后的,包括如上述提到的那几个重要的汇
编程序,它们都是在压缩内核vmlinuz 中的。因为Linux 中提供的内核包含了众多驱动和功
能,因而比较大,所以在采用压缩内核可以节省大量的空间。
(1)bootsect阶段
当 grub 读入vmlinuz 后,会根据bootsect(正好512bytes)把它自身和setup程序段读到
不大于0x90000 开始的的内存里(注意:在以往的引导协议里是放在0x90000,但现在有所
变化),然后grub 会跳过bootsect那512bytes 的程序段,直接运行setup里的第一跳指令。就
是说bzImage里bootsect的程序没有再被执行了,而bootsect.S在完成了指令搬移以后就退出
了。之后执行权就转到了setup.S的程序中。(2)setup阶段
setup.S的主要功能就是利用ROM BIOS中断读取机器系统数据,并将系统参数(包括内
存、磁盘等)保存到0x90000~0x901FF开始的内存中位置。
此外,setup.S还将video.S中的代码包含进来,检测和设置显示器和显示模式。
最后,它还会设置CPU 的控制寄存器CR0(也称机器状态字),从而进入32 位保护模
式运行,并跳转到绝对地址为0x100000(虚拟地址0xC0000000+0x100000)处。当CPU 跳
到0x100000时,将执行“arch/i386/kernel/head.S”中的startup_32。
(3)head.S阶段
当运行到head.S时,系统已经运行在保护模式,而head.S完成的一个重要任务就是将内
核解压。就如本节前面提到的,内核是通过压缩的方式放在内存中的,head.S通过调用misc.c
中定义的decompress_kernel()函数,将内核vmlinuz 解压到0x100000的。
接下来 head.S 程序完成完成寄存器、分页表的初始化工作,但要注意的是,这个head.S
程序与完成解压缩工作的head.S程序是不同的,它在源代码中的位置是arch/i386/kernel/head.S。
在完成了初始化之后,head.S就跳转到start_kernel()函数中去了。
(4)main.c阶段
start_kernel()是“init/main.c”中的定义的函数,start kernel()调用了一系列初始化函数,
进行内核的初始化工作。要注意的是,在初始化之前系统中断仍然是被屏蔽的,另外内核也
处于被锁定状态,以保证只有一个CPU用于Linux系统的启动。
在 start_kernel()的最后,调用了init()函数,也就是下面要讲述的INIT阶段。
2.2.3 init阶段
在加载了内核之后,由内核执行引导的第一个进程就是INIT进程,该进程号始终是“1”。
INIT 进程根据其配置文件“/etc/inittab”主要完成系统的一系列初始化的任务。由于该配置
文件是INIT进程执行的惟一依据,因此先对它的格式进行统一讲解。
inittab文件中除了注释行外,每一行都有如下格式:
id:runlevels:action:process
(1)id
id是配置记录标识符,由1~4个字符组成,对于getty或mingetty等其他login程序项,
要求id与tty的编号相同,否则getty程序将不能正常工作。
(2)runlevels
runlevels 是运行级别记录符,一般使用0~6 以及S和s。其中,0、1、6 运行级别为系
统保留:0 作为shutdown动作,1 作为重启至单用户模式,6 为重启;S和s意义相同,表示
单用户模式,且无需inittab文件,因此也不在inittab中出现。7~9级别也是可以使用的,传
统的UNIX 系统没有定义这几个级别。
runlevel可以是并列的多个值,对大多数action来说,仅当runlevel与当前运行级别匹配
成功才会执行。
(3)action
action字段用于描述系统执行的特定操作,它的常见设置有:initdefault、sysinit、boot、

bootwait、respawn等。
initdefault用于标识系统缺省的启动级别。当init由内核激活以后,它将读取inittab中的
initdefault 项,取得其中的runlevel,并作为当前的运行级别。如果没有inittab 文件,或者其
中没有initdefault项,init将在控制台上请求输入runlevel。
sysinit、boot、bootwait等action将在系统启动时无条件运行,忽略其中的runlevel。
respawn字段表示该类进程在结束后会重新启动运行。
(4)process
process字段设置启动进程所执行的命令。
以下结合笔者系统中的inittab 配置文件详细讲解该配置文件完成的功能:
1.确定用户登录模式
在“/etc/inittab”中列出了如下所示的登录模式,主要有单人维护模式、多用户无网络模
式、文字界面多用户模式、X-Windows 多用户模式等。其中的单人维护模式(run level为1)
是类似于Windows 中的“安全模式”,在这种情况下,系统不加载复杂的模式从而使系统能
够正常启动。在这些模式中最为常见的是3或5,其中本系统中默认的为5,也就是X-Windows
多用户模式。
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:5:initdefault:
2.执行内容/etc/rc.d/rc.sysinit
在确定了登录模式之后,就要开始将Linux 的主机信息读入Linux 系统,其内容就是文
件“/etc/rc.d/rc.sysinit”中的。查看此文件可以看出,在这里确定了默认路径、主机名称、
“/etc/sysconfig/network”中所记录的网络信息等。
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
3.启动内核的外挂模块及各运行级的脚本
在此,主要是选择模块的型态以进行驱动程序的加载。接下来会根据不同的运行级(run
level)加载不同的模块,启动系统服务。
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1

l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# When our UPS tells us power has failed, assume we have a few minutes
# of power left. Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in runlevel 5
x:5:respawn:/etc/X11/prefdm -nodaemon

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值