华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训
教材
民兵爆破地雷教材pdf初中剪纸校本课程教材衍纸校本课程教材排球校本教材中国舞蹈家协会第四版四级教材
“黑色经典”系列之《嵌入式 Linux系统开发技术详解——基于 ARM》
第 10章 制作 Linux根文件系统
本章目标
本章介绍了 Linux 根文件系统的组织结构,并且分析了 init 进程调用文件系统脚本初始
化的过程。只有掌握了文件系统的基本构成,才能自己动手定制 Linux文件系统。
根文件系统组织结构
INIT系统初始化过程
定制文件系统
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
Linux的根文件系统具有非常独特的特点,就其基本组成来说,Linux的根文件系统应该
包括支持 Linux 系统正常运行的基本内容,包含着系统使用的软件和库,以及所有用来为用
户提供支持架构和用户使用的应用软件。因此,至少应包括以下几项内容。
1.基本的文件系统结构,包含一些必需的目录比如:/dev,/proc,/bin,/etc,/lib,
/usr,/tmp等。
2.基本程序运行所需的库函数,如 Glibc/uC-libc。
3.基本的系统配置文件,比如 rc,inittab等脚本文件。
4.必要的设备文件支持:/dev/hd*,/dev/tty*,/dev/fd0。
5.基本的应用程序,如 sh,ls,cp,mv等。
以下章节的内容将对制作 Linux根文件系统的过程作一些详细地分析,目的是使读者能
够较快地理解如何在一个目标系统(Target)建立起操作系统的根文件系统,进而加快开发
流程
快递问题件怎么处理流程河南自建厂房流程下载关于规范招聘需求审批流程制作流程表下载邮件下载流程设计
。
10.1 根文件系统目录结构
文件系统是在任何操作系统中都非常重要的概念,简单地讲,文件系统是操作系统用于
明确磁盘或分区上的文件的方法和数据结构,即在磁盘上组织文件的方法。文件系统的存在,
使得数据可以被有效而透明地存取访问。
进行嵌入式开发,采用 Linux作为嵌入式操作系统必须要对 Linux文件系统结构有一定
的了解。每个操作系统都有一种把数据保存为文件和目录的方法,因此它才能得知添加、修
改之类的改变。在 DOS操作系统之下,每个磁盘或磁盘分区由独立的根目录,并且用唯一的
驱动器标识符来表示,如:C:\, D:\等。不同磁盘或不同的磁盘分区中,目录结构的根目录是
各自独立的。而 Linux的文件系统组织和 DOS操作系统不同,它的文件系统是一个整体,所
有的文件系统结合成一个完整的统一体,组织到一个树形目录结构之中,目录是树的枝干,
这些目录可能会包含其他目录,或是其他目录的“父目录”,目录树的顶端是一个单独的根目
录,用/表示。在 Linux下可以看到系统的根目录组成内容,如图 10.1所示。
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
图 10.1 Linux下根目录内容
在上图中,弧线内部的部分即为 Linux根目录的组成。
10.1.1 FHS目录结构
Linux遵守文件系统科学分类
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
(Filesystem Hierarchy Standard,FHS),一个定义许多
文件和目录的名字和位置的标准,该项标准可以在 http://www.pathname.
com/FHS找到,FHS也是用来组织 Linux和 Unix文件的方法,它使得 Linux文件系统布局实
现了标准化,一个 Linux的根文件系统目录结构如图 10.2所示。
根文件系统目录
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
根 文 件 系 统 /
/ d e v
/ r o o t
/ u s r
/ v a r
/ h o m e
/ p r c o
/ b i n
/ s b i n
/ e t c
/ b o o t
/ l i b
/ m n t
/ t m p
/ i n i t r d
图 10.2 Linux根文件系统结构
1./dev设备文件
在/dev目录下是一些称为设备文件的特殊文件,用于访问系统资源或设备,如软盘,硬
盘,系统内存等。设备文件的概念是 DOS和 Windows操作系统中所没有的,在 Linux下,
所有设备都被抽象成了文件,有了这些文件,用户可以像访问普通文件一样方便地访问系统
中的物理设备。例如:你可以像从一个文件中读取数据一样,通过读取/dev/mouse 文件从鼠
标读取输入信息。在/dev目录下,每个文件都可以用mknod命令建立,各种设备所对应的特
殊文件以一定规则来命名。以下是/dev目录下的一些主要设备文件。
(1)/dev/console
系统控制台,也就是直接和系统连接的监视器。
(2)/dev/hd
在 Linux系统中,对于 IDE接口的整块硬盘表示为/dev/hd[a-z],对于硬盘的不同分区,
表示方法为/dev/hd[a-z]n,其中 n表示的是该硬盘的不同分区情况。例如/dev/hda指的是第一
个硬盘,hda1 则是指/dev/hda 的第一个分区。如系统中有其他的硬盘,则依次为/dev/hdb、
/dev/hdc等;如有多个分区则依次为 hda1、hda2等。
(3)dev/fd
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
软驱设备文件。通过前面对系统 IDE 接口硬盘的表示方法不难理解:/dev/fd0 是指系统
的第一个软驱,也就是通常所说的 A盘,/dev/fd1是指系统的第二个软驱。
(4)dev/sd
SCSI接口磁盘驱动器。理解方法和 IDE接口的硬盘相同,只是把 hd换成 sd。目前,Linux
下驱动 USB存储设备的方法采用模拟 SCSI设备,所以 USB存储设备的表示方法与 SCSI接
口硬盘的表示方法相同。
(5)dev/tty
设备虚拟控制台。如:/dev/tty1 指的是系统的第一个虚拟控制台,/dev/tty2 则是系统的
第二个虚拟控制台。
(6)dev/ttyS*
串口设备文件。dev/ttyS0是串口 1,dev/ttyS1是串口 2。
2./root root用户主目录
root 目录中的内容包括:引导系统的必备文件、文件系统的挂装信息、设备特殊文件、
以及系统修复工具和备份工具等。由于是系统管理员的主目录,普通用户没有访问权限。
3./usr
/usr 是最庞大的目录,该目录中包含了一般不需要修改的命令程序文件、程序库、手册
和其他文档等。Linux内核的源代码就放在/usr/src/linux里。
4./var
该目录中包含经常变化的文件,例如打印机、邮件、新闻等的脱机目录、日志文件以及
临时文件等。因为该文件系统的内容经常变化,因此如果和其他文件系统,如/usr 放在同一
硬盘分区,文件系统的频繁变化将会提高整个文件系统的碎片化程度。
5./home
用户主目录的默认位置。例如,一个名为 LY 的用户主目录将是/home/LY,系统的所有
用户的数据保存在其主目录下。
6./proc
需要注意的是,/prco文件系统并不保存在系统的硬盘中,操作系统在内存中创建这一文
件系统目录,是虚拟的目录,即系统内存的映射,其中包含一些和系统相关的信息,例如 CPU
的信息等。
7./bin
该目录包含二进制(binary)文件的可执行程序,这里的 bin本身就是 binary的缩写,许
多 Linux命令就是放在该目录下的可执行程序,例如 ls、mkdir、tar等命令。
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
8./sbin
与 bin目录类似,存放系统编译后的可执行文件、命令,如常用到的 fsck、lsusb等指令,
通常只有 root用户才有运行的权限。
9./etc
/etc目录在 Linux文件系统中是一个很重要的目录,Linux的很多系统配置文件就在该目
录下,例如系统初始化文件/etc/rc等。Linux正是靠这些文件才得以正常地运行,用户可以根
据实际需要来配置相应的配置文件,以下列举一些配置文件。
(1)/etc/rc或/etc/rc.d
启动或改变运行级别时运行的脚本或脚本的目录。大多数的 Linux发行版本中,启动脚
本位于/etc/rc.d/init.d中,系统最先运行的服务是那些放在/etc/rc.d目录下的文件,而运行级别
在文件/etc/inittab里指定,这些会在后面的内容中详细讲到。
(2)/etc/passwd
/etc/passwd是存放用户的基本信息的口令文件。该口令文件的每一行都包含由 6个冒号分隔
的 7个域,其中的域给出了用户名、真实姓名、用户起始目录、加密口令和用户的其他信息。
· username:用户名。
· passwd:是口令密文域。密文是加密过的口令。如果口令经过 shadow则口令密文域
只显示一个 x,通常,口令都应该经过 shadow 以确保安全。如果口令密文域显示为*,则表
明该用户名有效但不能登录。如果口令密文域为空则表明该用户登录不需要口令。
· uid:系统用于唯一标识用户名的数字。
· gid:表示用户所在默认组号。
· comments:用户的个人信息。
· directory:定义用户的初始工作目录。
· Shell:指定用户登录到系统后启动的外壳程序。
(3)etc/fstab
指定启动时需要自动安装的文件系统列表。通常来讲,如果用户在使用过程中需要手动
加载许多文件系统,这会带来不小的工作量。为了避免这样的麻烦,让系统在启动的时候自
动加载这些文件系统,Linux 中使用/etc/fstab 文件来完成这一功能。fstab 文件中列出了引导
时需安装的文件系统的类型、加载点及可选参数。所以进行相应的配置即可确定系统引导时
加载的文件系统。
(4)etc/inittab
init的配置文件,在后面的内容会详细讲到。
10./boot
该目录存放系统启动时所需的各种文件,如内核的镜像文件,引导加载器(bootstrap
loader)使用的文件 LILO和 GRUB。
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
11./lib
标准程序设计库,又叫动态链接共享库,作用类似于Windows里的.dll文件。
12./mnt
该目录用来为其他文件系统提供安装点,例如可以在该目下新建一目录 floppy用来挂载
软盘,同样可以新建一目录 cdrom(可以用任意名称)用来挂载光盘等。比如在 Linux 下的
终端执行下面的语句:
# mount –t vfat dev/hda1 /mnt/win_D
即可将硬盘的第一个分区挂载到 Linux下的/mnt/win_D目录中。
13./tmp公用的临时文件存储点
14./initrd
用来在计算机启动时挂载 initrd.img映像文件以及载入所需设备模块的目录,需要注意的
是,不要随便删除/initrd/目录,如果删除了该目录,将无法重新引导系统。
10.1.2 文件存放规则
为了实现各种 Linux版本系统的标准化,各种不同的 Linux版本都会根据 FHS(Filesystem
Hierarchy Standard)标准来进行系统管理,这也使得 Linux系统的兼容性大大提高。FHS规
定了两级目录,第一级是根目录下的主要目录,根据目录名称可以得知其中应该放置什么样
的文件,比如/etc应该放置各种配置文件,/bin和/sbin目录下应该放置相应的可执行文件等;
第二级目录则主要针对/usr和/var做出了更深层目录的定义。
Unix/Linux 系统很长时间以来一直是在“什么文件放在哪里”的基础之上建立文件存放
规则的,并且按照这些规则把文件放进相应分级结构里。文件系统分级结构标准(FHS)试
图以一种合乎逻辑的方式定义这些规则,而且在 Linux上得到了广泛应用。按照 FHS标准,
在 Linux下存放文件主要有以下的一些规则。
1.把全局配置文件放入/etc目录下。
2.将设备文件信息放入/dev目录下,设备名可以作为符号链接定位在/dev中或/dev子目
录中的其他设备存在。
3.操作系统核心定位在/或/boot,若操作系统核心不是作为文件系统的一个文件存在,
不应用它。
4.库存放的目录是/lib。
5.存放系统编译后的可执行文件、命令的目录是/bin,/sbin,/usr。
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
10.2 添加系统文件
10.2.1 添加共享链接库
Linux下的共享函数库在根文件系统下的/lib目录中,应用程序通常都是需要共享库才可
以工作的,所以添加共享库对于根文件系统是必需的。图 10.3 是一个 Linux 系统下/lib 目录
下的内容。
图 10.3 Linux下/lib目录的内容
每个 Linux系统或嵌入式 Linux系统都需要一个 C库。C库提供了常用的文件操作(比
如打开、读/写)、内存管理操作(malloc 和 free)等其他的一些函数。许多基于 X86 架构的
Linux系统使用 Glibc库。但是对于嵌入式系统开发来说,使用 Glibc对于内存的消耗也较多,
如果内存资源大小受到严格限制的话,采用 Glibc 是不可接受的。uClibc 是针对嵌入式系统
开发的,这是一个稳定的、兼容 Glibc的替代品,所以它力图成为完整但结构紧凑的 C库。
在绝大多数情况下,针对 uClibc编译的应用程序和工具与针对 Glibc编译的没有区别。
在根文件系统的/lib目录下主要包含以下 4种类型的文件。
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
1.实际的共享链接库
这类文件名的格式为 lib libname version.so,其中,libname是共享库的名称,version是
版本编号。例如:glibc 2.2.3的数学链接库的名称为 libm-2.2.3.so。
2.主修订版本的符号链接
主修订版本的符号链接的格式为 lib libname.so.major-revision-version,例如,C链接库的
符号链接的名称为 libc.so.6。程序一旦链接了特定的链接库,它将会参用其符号链接,程序
启动时,加载器在加载程序之前,会因此加载该文件。
3.与版本无关的符号链接指向主修订版本的符号链接
这些符号链接的主要功能是为需要链接特定链接库的所有程序提供一个通用的条目,与
主修订版本的编号或 glibc涉及的版本无关。这些符号链接的格式为 lib libname.so。
4.静态的链接库
选择以静态方式链接链接库的应用程序会使用这些文件,这些文件的格式为: lib
libname.a。
在 Linux程序开发过程当中,应用程序的执行离不开共享链接库的支持,所以需要将其
中的一些文件复制到用户目标板的根文件系统的相应位置。事实上,需要的文件是共享链接
库和主修订版本的符号链接。
为了明确用户应用程序需要链接哪些链接库,通常可以使用系统下的命令 lddl 来列出
应用程序要以存哪些动态链接库。例如查看文件复制命令 cp所依赖的共享库,可以执行如
下指令。
# ldd /bin/cp
libtacl.so.1 => /lib/libacl.so.1 (0x00701000)
libselinux.so.1 => /lib/libselinux.so.1(0x00b87000)
libc.so.6 => /lib/tls/libc.so.6 (0x0064b000)
libattr.so.1 => /lib/libattr.so.1(0x00ba1000)
/lib/ld-linux.so.2 (0x40000000)
“=>”左边的表示该程序所需共享库的符号链接名称,右边表示由 Linux 的共享库系统
找到的对应的共享库在根文件系统中的实际位置,所以可看到执行 cp指令需要用到 5个共享
库。默认情况下,动态链接库的配置文件/etc/ld.so.conf 中包含有默认的共享库搜索路径,通
过查看改配置文件来了解默认的共享库搜索路径。例如:
#vi /etc/ld.so.conf
/usr/X11R6/lib
/usr/lib
/usr/local/lib
/usr/lib/qt-3.3/lib
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
以上是笔者 Fedora Core Linux下的动态链接库的配置文件的内容。通常情况下,许多开
放源代码的程序或函数库都会默认安装到/usr/local 目录下的相应位置(/usr/local/bin 或
/usr/local/lib),以便与系统自身的程序或函数库相区别。而许多 Linux 系统的/etc/ld.so.conf
文件中默认又不包含/usr/local/lib。因此,往往会出现已经安装了共享库,但是却无法找到共
享库的情况。这时,就应该检查/etc/ld.so.conf文件,如果其中缺少/usr/local/lib目录,就应该
添加进去。
如同 Glibc一样,uClibc也包含了若干链接库,因为 uClibc是 Glibc的替代品,所以 uClibc
中各个组件的名称及其用法如同 glibc中相应的组件,但是 uClibc并不实现Glibc的所有组件,
uClibc 只会实现 ld、libc、libcrypt、libdl、libm、libpthread、libresolv 和 libutil。决定好所需
的组件清单之后,接着可以将它们及相关的符号链接复制到目标板的根文件系统中的/lib 目
录中,如下面的命令会将 uClibc的所有组件复制到目标系统的根文件系统。
# cd /lib ;主机的根文件系统的/lib目录
# cp *-*.so /rootfs/lib
# cp -d *.so.[*0-9] /rootfs/lib
第一个 cp复制命令会复制实际的共享链接库,第二个 cp复制命令会复制主修订版本的
符号链接。当把 uClibc组件安装到目标系统的根文件系统中以后,应用程序在执行的过程中
就可以使用这些共享库了。
10.2.2 添加内核模块
接下来了解 Linux系统添加内核模块的过程。首先来阐述内核模块的概念,简单地讲,
内核模块是一些可以让系统内核在需要时加载并且能够执行;在不需要的时候可以被系统卸
载掉的代码。添加内核模块是嵌入式 Linux 开发中非常有用而又很重要的一项环节,在嵌入
式系统开发过程当中,如果想增加系统的某部分功能,可以有 2种方法:一种方法是编译内
核:即把相应部分在编译内核时候编译进去,另一种方法就是采用动态加载,即动态调用系
统所需要的内核模块。
采用以上的两种方法各有优缺点,如果编译到内核中,在内核启动时就可以自动支持相
应部分的功能,这样的优点是方便、速度快,机器一启动,你就可以使用这部分功能了;缺
点是会使内核变得庞大起来,不管你是否需要这部分功能,它都会存在,对于经常用到的部
分直接可以考虑直接编译到内核中,比如网卡。如果采用后一种方法也就是编译成模块,就
会生成对应的.o文件,在使用的时候可以动态加载,优点是不会使内核过分庞大,缺点是开
发者得自己来调用这些模块。下面就这两种方法分别介绍为系统添加内核模块的过程。
1.在内核编译过程中自动添加内核模块
内核编译的详细过程会在本书的其他章节中做出详细地介绍,其中对于模块支持的设置
选项中包含有 3项内容。
——>Loadable module support
[ * ] Enable loadable module support
[ ] Set version information on all module symbols
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
[ ] Kernel module loader
第 1项的内容是指是否支持动态加载内核模块,如果不是所有需要的内容都编译到内核
里,应该选择该项;第 2项的内容可以不选;第 3项的内容是指让内核在启动时就可以加载
所需的模块,这一选项应该选上。在配置内核相关选项之后,对于模块的管理还需执行如下
的指令。
# make modules
# make modules_install
make modules和 make modules_instal命令分别生成相应的模块和把模块拷贝到需要的目
录中,具体的解释可以参考本书内核编译的相关章节。内核编译之后,就可以将编译内核过
程中生成的内核模块复制到目标系统的根文件系统,接着还需要为目标开发系统添加内核模
块的配置文件/etc/modprobe.conf,以便系统在运行的时候可以自动加载内核模块,图 10.4所
示就是 Fedora Core 4下的/etc/modprob.conf文件。
图 10.4 /etc/modprob.conf文件
开机自动挂载模块位于该配置文件中,在该文件中,写入了模块的加载命令或模块的别
名的定义等;如果想让一些模块开机自动加载,就可以在该配置文件中写入。比如在
modprobe.conf配置文件中下面的语句。
alias eth0 8139too
这样系统启动的时候,首先会加载 8139too 模块,同时指定网络设备 8139too 的别名为
eth0。
2.动态添加内核模块
Linux为了不需要重新编译内核就可以动态加载内核模块,引入了可加载内核模块 LKM
(Loadable Kernel Modules)的概念,模块不被编译在内核中,LKM扩展了操作系统内核的功
能而不需要重新编译内核,如果想在 Linux 下查看内核已经加载的内核模块,可以通过执行
lsmod命令来查看(读取/proc/modules文件获取所需信息),如图 10.5所示。
在图 10.5中,module指的是模块名称,Size指的是该模块所占内存页面的大小,而 Used
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
by指的是该模块被系统调用的次数。
动态加载内核模块有 2种方法,以下分别叙述。
(1)采用 modprobe命令加载
modprobe常用的功能就是挂载模块,在挂载某个内核模块的同时,这个模块所依赖的模
块也被同时挂载,modprob指令的格式如下。
图 10.5 lsmod命令查看系统加载的内核模块
modprobe [-v] [-V] [-C config-file] [-n] [-i] [-q] [-o
]
[parameters...]
modprobe -r [-n] [-i] [-v] ...
modprobe -l -t [ -a ...]
例如:
[root@localhost zhang]# modprobe 8139too #挂载 8139too 模块;
[root@localhost zhang]# modprobe vfat #挂载 vfat 模块
注意
这里的模块名是不带有后缀的。
(2)采用 insmod命令加载
insmod指令和 modprobe指令在功能上有所区别,modprobe 在加载模块时不用指定模块
文件的绝对路径,也不用带模块文件的后缀.o 或.ko;而 insmod 需要的是模块的所在目录的
绝对路径,并且一定要带有模块文件名后缀的(modulefile.o或 modulesfile.ko)。例如:
# insmod /lib/modules/2.6.9-11.EL/Kernel/drivers/pci/hotplug/capiphp.ko
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
注意
采用该种方法添加内核模块要有绝对路径,同时要有完整文件名的后缀。
10.2.3 添加设备文件
Linux中任何对象(包括设备)都可以认为是文件。Linux将设备分为最基本的 2大类:
一类是字符设备(Character Device),另一类是块设备(Block Device)。字符设备特殊文件进
行 I/O 操作不经过操作系统的缓冲区,而块设备特殊文件用来同外设进行定长的包传输。字
符特殊文件与外设进行 I/O 操作时每次只传输一个字符。而对于块设备特殊文件来说,在外
设和内存之间一次可以传送一整块数据。在 Linux 根文件系统中,设备文件所在的目录是
/dev,图 10.6显示了 Fedora Core 4.0 linux目录/dev中的内容。
图 10.6 Linux下/dev目录中的内容
可以看到/dev目录下有非常多的设备文件,事实上,嵌入式 Linux是个定制的系统,目
标系统的设备文件只要满足实际开发需求即可,所以在/dev目录下只添加必要的设备文件即
可。Linux下添加设备文件可以采用以下的方法。
1.使用mknod指令来添加设备
举例说明在根文件系统下使用 mknod指令添加设备文件的过程。
#cd /dev
#mknod –m 666 null c 1 3
#mknod –m 666 zero c 1 5
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
#mknod -m 666 /dev/ttyS0 c 4 64
#mknod -m 600 console c 5 1
注意
所有写入设备/dev/null的信息都将被隐藏。
添加好基本的设备文件之后,在根文件系统的/dev目录下还必须包括必要的符号链接,
可以使用“ln–s链接名链接目标”命令建立这些链接,比如:
# ln –s /proc/self/fd fd
# ln –s fd/0 stdin
# ln -s fd/1 stdout
# ln -s fd/2 stderr
2.在/dev目录下采用 MAKEDEV(符号链接/sbin/MAKEDEV)来建立设备文件
例如需要在根文件系统中添加 tty0设备可以输入如下指令。
# cd /dev
# ./MAKEDEV ttyS0
10.3 init系统初始化过程
系统的引导和初始化是操作系统实现控制的第一步,是集中体现系统整体性能至关重要
部分。了解系统的初始化过程,对于进一步掌握后续开发是十分有帮助的。首先来了解一下
Linux内核的启动过程,如图 10.7所示
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
。
开机启动
BIOS自检
Lilo/Grub
Kernel引导
启动 init进程
启动Mingetty
Login
进入 Shell
启动完成
执行 rc.sysinit
脚本
执行/etc/rc.d/
rc然后返回 init
第一阶段
第二阶段
图 10.7 Linux内核启动过程示意图
通常,Linux内核的启动可以分为两个阶段。
1.在第 1 个阶段完成硬件检测、初始化和内核的引导;在内核启动的第 1 个阶段,系
统按 BIOS中设置的启动设备(通常是硬盘)启动,接着利用 Lilo/Grub程序来进行内核的引
导工作,内核被解压缩并装入内存后,开始初始化硬件和设备驱动程序。
2.在第 2个阶段就是 init的初始化进程。所谓的 init进程,是一个由内核启动的用户
级进程,也是系统上运行的所有其他进程的父进程,它会观察其子进程,并在需要的时候
启动、停止、重新启动它们,主要用来完成系统的各项配置。init 从/etc/inittab 获取所有信
息。init程序通常在/sbin或/bin下,它负责在系统启动时运行一系列程序和脚本文件,而 init
进程也是所有进程的发起者和控制者。内核启动(内核已经被载入内存,开始运行,并已
初始化所有的设备驱动程序和数据结构等)之后,便开始调用 init 程序来进行系统各项配
置,也即成为系统的第一个进程,该进程对于 Linux系统正常工作是十分重要的。
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
10.3.1 inittab文件
Linux启动时,运行一个叫作 init的程序,然后根据运行级启动后面的任务,包括多用户
环境,网络等。所谓的运行级就是操作系统当前正在运行的功能级别。这个级别从 0~6,具
有不同的功能。这些级别在/etc/inittab文件里指定。这个文件是 init 程序寻找的主要文件,init
进程中所做的每一步配置工作都由/etc/initab 中的内容来决定的。以下是 Fedro Core4 的
/etc/inittab文件代码。
# inittab This file describes how the INIT process should set up
# the system in a certain run-level.
#
# Author: Miquel van Smoorenburg,
# Modified for RHS Linux by Marc Ewing and Donnie Barnes
# 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:
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
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"
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
# 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
从代码中可以看到,etc/inittab中语句的每一行包含 4个域,格式如下。
Id:runlevels:action:process
(1)id:id是指入口标识符,它是一个字符串,是由两个独特的字元所组成的标识符号,
对于 getty或 mingetty等其他 login程序项,要求 id与 tty的编号相同,否则 getty程序将不能
正常工作。
(2)run levels(运行级别)运行级别会指出下一个操作域中的 action以及 process域会在
哪些 runlevel中被执行。而在正常的启动程序之后,root用户可以使用 telinit这个指令来改变
系统的 runlevel。假定在 Linux系统中 runlevel的预设值是 5,那么只有那些每一列中 runlevel
域的值为 5时,后面的 process才会被执行。所以,如果系统的 runlevel值不同的话,所执行
的 process也不一样,所以系统启动的资源配置情况在每个不同的 runlevel下就会有差异。
(3)action:action域指出的是 init程序执行相应 process时,对 process所采取的动作。比
如:只执行 process一次,还是在它退出时重启。
(4)process为具体的执行程序。程序后面可以带参数。
现将 etc/inittab文件代码分析如下。
运行级别定义
# 0 - 停机(不要把 initdefault 设置为 0,否则开机之后就会自动关机 )
# 1 - 单用户模式
# 2 - 多用户模式,但是没有 NFS
# 3 - 完全多用户模式
# 4 - 没有使用
# 5 – X-windows模式
# 6 – 系统重新启动 (不要把 initdefault 设置为 6,否则开机之后就会重启 )
id:5:initdefault:
解释:该命令指出缺省的运行级别为 5,即开机后进入 X-window模式。
si::sysinit:/etc/rc.d/rc.sysinit
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
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
解释:系统启动之后自动执行/etc/rc.d/rc.sysinit脚本,而且指出当运行级别为 5时,以 5
为参数运行/etc/rc.d/rc 5脚本,init进程将等待其返回(wait)。
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
解释:在启动过程中如果按 Crtl-Alt-Delete,将执行/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"
解释:如果系统带有 UPS电源工作,该行命令设定系统在掉电时提示“电源关闭,系统
正在关闭”,并且在 2min后自动关机。
# 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
解释:init进程打开 6个终端(虚拟控制台),以 tty n为参数执行/sbin/mingetty程序,打
开 tty n终端用于用户登录。
# Run xdm in runlevel 5
x:5:respawn:/etc/X11/prefdm –nodaemon
解释:在级别 5上运行 xdm程序,提供 xdm图形方式登录界面,并在退出时重新执行
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
(respawn)。
10.3.2 System V init启动过程
在介绍 System V init启动过程之前,先来了解一下 System V的由来。简单地讲,System
V 也被称作为 AT&T System V,是 Unix 操作系统众多版本中相当重要的一个。它最初由
AT&T开发,在 1983年第一次发布。一共发行了 4个 System V的主要版本:版本 1、2、3
和 4。System V Release 4是其中最成功的版本,它具有一些 Unix共同的特性,比如 Sys V init
初始化脚本。
概括地讲,Linux \Unix系统一般有两种不同的初始化启动方式。
· BSD system init
· System V system init
System V 模式将启动档案存放在/etc/...或/etc/rc.d/...及其下的一堆子目录中,主要内容
如下。
/etc/rc.d/init.d
/etc/rc.d/rc0.d
/etc/rc.d/rc1.d
/etc/rc.d/rc2.d
/etc/rc.d/rc3.d
/etc/rc.d/rc4.d
/etc/rc.d/rc5.d
/etc/rc.d/rc6.d
rc
rc.local
rc.sysinit
大多数发行套件的 Linux都使用了与 System V init相仿的 init也就是 Sys V init,它比传
统的 BSD system init更容易使用而且更加灵活,Sys V init主要思想是定义了不同的“运行级
别(runlevel)”。通过配置文件/etc/inittab,定义了系统引导时的运行级别,进入或者切换到
一个运行级别时做什么。每个运行级别对应一个子目录/etc/rc.d/rc n.d(n表示运行级别 0~6),
例如,rc0.d便是 runlevel 0启动脚本存放的目录,rc3.d是 runlevel 3,其他依此类推。rc n.d
中的脚本并不是各自独立的,其实它们都通过符号链接连接到/etc/rc.d/init.d 中的脚本。图
10.8是系统 rc5.d目录中的内容列表。
华清远见——嵌入式培训专家 http://www.farsight.com.cn
华清远见<嵌入式 Linux系统开发班>培训教材
图 10.8 /etc/rc.d/rc5.d内容列表
可以看到里面的内容是一些以字母‘S’和‘K’开头的符号链接,链接指向/etc/rc.d/init.d
中的脚本,每个脚本对应一项服务程序。以 S开头的,表示 Start 启动之意,以 start 为参数
调用该脚本;以 K 开头的,则是表示 stop 停止,以 stop 为参数调用该脚本,这就使得 init
可以启动和停止服务。事实上,可以通过手动执行来启动或停止相关服务,比如,可以执行
下面的语句分别来启动和停止 NFS服务。
# /etc/rc.d/init.d/nfs start
启动 NFS服务 [OK]
# /etc/rc.d/init.d/nfs stop
停止 NFS服务 [OK]
以下是一个大致的 System V init过程。
(1)init过程执行的第一个脚本文件是/etc/rc.d/rc.sysinit,限于篇幅的原因,此处不再列出该脚
本文件的详细内容,/etc/rc.d/rc.sysinit主要做在各个运行级别中进行初始化工作,包括以下内容。
· 启动交换分区。
· 检查磁盘。
· 设置主机名。
· 检查并挂载文件系统。
· 加载并初始化硬件模块。
(2)执行缺省的运行级模式。
《嵌入式 Linux系统开发技术详解——基于 ARM》——第 10章、制作 Linux根文件系统
华清远见<嵌入式 Linux系统开发班>培训教材
这一步的内容主要在/etc/inittab中体现,inittab文件会告诉 init进程要进入什么运行级别,
以及在哪里可以找到该运行级别的配置文件。
(3)执行/etc/rc.d/rc.local脚本文件。
这也是 init过程中执行的最后一个脚本文件,所以用户可以在这个文件中添加一些需要在登录
之前执行的命令,默认地,/etc/rc.d/rc.local会用使用系统的内核版本和机器类型创建一个登录标志。
(4)执行/bin/login程序。
login程序会提示用户输入账号及密码,接着编码并确认密码的正确性,若二者相合,则
为使用者进行初始化环境,并将控制权交给 Shell。
10.3.3 Busybox init启动过程分析
有关 Busybox的详细介绍会在下一章提到,此处着重介绍 Busybox init启动过程。与一
些标准的 init比如 Sys v init一样,Busybox也具有处理系统初始化过程的能力,由于 Busybox
自身的一些特点,Busybox init非常适合在嵌入式系统开发中使用,被誉为“嵌入式 Linux的
瑞士军刀”,它可以为嵌入式系统提供主要的 init功能,通过定制可以做得非常精炼。
默认的情况下,Busybox安装之后会生成一个可执行程序 Busybox,在目录…/_install/bin
下,查看 Busybox的属性可以知道/sbin/init是其符号链接,如果使用 Busybox做 Ramdisk