linux之文件系统制作及移植

目标:用busybox定制一个很小的文件系统。

一、文件系统介绍

文件系统:是操作系统用于明确磁盘或分区上的文件的方法和数据结构,即在磁盘上组织文件的方法。Linux文件系统是一个完整的统一体,组织到一个树形目录结构中。

Linux遵守文件系统科学分类标准FHS,一个定义许多文件和目录的名字和位置的标准。

w      主要规则如下:

l     配置文件放在/etc目录下

l     设备文件放在/dev目录下

l     库文件放在目录/lib目录下

l     存放系统编译后的可执行文件、命令的目录是/bin、/sbin、/usr/bin、/usr/sbin目录

在嵌入式系统中,根目录下的很多目录都可以删除,如下:

l     为多用户提供可扩展环境的所有目录都应该删除;如(/home,/mnt,/root)

l     根据引导加载情况,/boot目录可以删除。

其余的目录

l     /bin,/dev,/etc,/proc,/sbin,/usr,/lib都是不可缺少的。

二、构建根文件系统

Linux的根文件系统包括支持linux系统正常运行的基本内容,至少应包括以下几项内容:

l     基本的文件系统结构,如bin、dev、etc、sbin,lib、usr、proc,sys,tmp。

l     基本程序运行所需的动态库。

l     基本的系统配置文件。

l     必要的设备文件支持。

l     基本的应用程序,如sh、ls、cp等。

.proc,sys,tmp   是Linux内核信息的抽象文件接口,大量内核中的信息以及可调参数都被作为常规文件映射到目录树中. 如在/etc/init.d/rcS中加入下面一句:

/bin/mount –a 

 Mountall filesystems (of the given types) mentioned in fstab.

 “mount -a”命令后将挂载proc,tmpfs 等包含在该文件中的所有的文件系统。

 

 /ect/fstab 的内容如下:

       proc/proc proc defaults 0 0   加载proc文件系统

       none/tmp ramfs defaults 0 0   

       sysfs/sys sysfs defaults 0 0

      

       则已经挂载的设备可以通过命令查询#lsmod

       所挂载的设备的设备号可查询#cat /proc/devices

/proc是虚拟文件系统。Linux 内核提供了一种通过 /proc 文件系统在运行时访问内核内部数据结构、改变内核设置的机制和接口。proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间,/proc文件系统是一种内核和内核模块用来向进程 (process) 发送信息的机制 (所以叫做 /proc)。这个伪文件系统让你可以和内核内部数据结构进行交互,获取有关进程的有用信息

构建根文件系统就是往相应的目录添加相应的文件。如:

l     在/dev添加设备文件,

l     在/etc添加配置文件,

l     在/bin添加命令或者程序,

l     在/lib添加动态库等。

添加设备文件

Linux对所有外部设备的访问都是以文件的形式来进行;

在Linux系统中,可以找到设备对应的文件,称为设备文件;

设备文件(也叫做设备节点)都存放在/dev的目录下

w       在/dev目录下,建立设备文件的命令是mknod;

如:mknod /dev/led c  231  0 

上面例子中 “/dev/led”是设备文件路径;“c”是指定为字符设备;“231”是主设备号(insmod a.ko 后在 /proc/devices 下查看);“0”是次设备号。

w       Linux系统是靠主、次设备号来联系驱动程序和设备文件的;

(Key key.c key.ko—模块 insmod key.ko 主设备号160 )

三、BusyBox介绍

从名字上直接理解,Busybox是一个“繁忙的盒子”,其实,Busybox可以理解为一个Linux的命令集合,我们在进行Linux操作时所需要的 常用命令,都可以在Busybox里找到,但Busybox又不是简单的将所有的命令集合在一起,它采用了一种非常巧妙的方式,即“使用一个程序完成所有 的事”。 

平时我们用ls、vi等命令,都要用到glibc的相关调用,所以如果每个命令都静态链接这些调用,每个命令都会很大,因此在通常的发行版中,都会动态链 接glibc,可是glibc的动态库本身就很大,这在PC+Linux平时上还可以接受,但在嵌入式系统中,这就太大了,而且又不是所有的库函数都使 用。

一般采用两种解决办法,一种是裁剪glibc,另一种就是Busybox的办法,即把lsvi等程序的main函数改一下名,全部链接在一起,然后静态链接glibc,这样,只有需要的调用才会链接进来,整个Busybox程序可能都比glibc的动态库小。

因此,Busybox的工作原理是根据文件名来决定用户想调用的是那个程序,例如,如果你的busybox程序的文件名是ls,运行的就是ls,是vi,就运行vi。 

下面介绍一下ARM-Linux平台的Busybox-1.00交叉编译与使用步骤:

 将文件busybox-1.00.tar.gz拷贝到Linux目录,执行如下命令解压文件: 
       #tar xzvf AT91RM9200-busybox-1.00.tar.gz
      当文件解压完成以后,会自动生成busybox-1.00目录,进入该目录,并执行如下命令进行编译:
       #make clean ;清除旧的编译文件
       #make menuconfig 在这里修改一些必要的选项

  #make ARCH=arm CROSS_COMPILE=arm-linux-CONFIG_PREFIX=/root/build_rootfs/rootfs all install

busybox是一个集成了一百多个最常用linux命令和工具的软件,它甚至还集成了一个http服务器和一个telnet服务器,而所有这一切功能却只有区区1M左右的大小.我们平时用的那些linux命令就好比是分力式的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行文件里,功能基本不变,而大小却小很多倍,在嵌入式linux应用中,busybox有非常广的应用。

Busybox 提供的程序包括:

l     具有shell功能,如csh

l     提供一个迷你的vi编辑器

l     提供系统不可或缺的/sbin/init程序

l     其他的系统基本命令,如:ls,mkdir,ifconfig等。

BusyBox 编译选项

make 目标

说明

help

显示 make 选项的完整列表

defconfig

启用默认的(通用)配置

allnoconfig

禁用所有的应用程序(空配置)

allyesconfig

启用所有的应用程序(完整配置)

allbareconfig

启用所有的应用程序,但是不包括子特性

config

基于文本的配置工具

menuconfig

N-curses(基于菜单的)配置工具

all

编译 BusyBox 二进制文件和文档(./docs)

busybox

编译 BusyBox 二进制文件

clean

清除源代码树

distclean

彻底清除源代码树

sizes

显示所启用的应用程序的文本/数据大小

 

四、实验步骤

1、建立工作目录(这里建议统一用这个路径,否则在指定安装路径及copy库文件的路径都要改)

设定工作目录为/root/build_rootfs/, 下载busybox到该目录

mkdir /root/build_rootfs

 

2、 建立根目录, 该目录就是我们要移植到目标板上的目录,对于嵌入式的文件系统,根目录下必要的目录包括bin,dev,etc,usr,lib,sbin,proc sys tmp。

 

cd /root/build_rootfs

mkdir rootfs

cd rootfs

mkdir bin dev etc usr lib sbin proc sys tmp

mkdir usr/bin usr/sbin usr/lib

/bin bin是Binary的缩写。这个目录存放着最经常使用的命令。

/sbin s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。

/dev dev是Device(设备)的缩写。该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。

/etc这个目录用来存放所有的系统管理所需要的配置文件和子目录。

/usr 我们要用到的很多应用程序和文件几乎都存放在usr目录下

  /usr/bin存放着许多应用程序;

/usr/sbin存放root超级用户使用的管理程序;

/usr/lib存放一些常用的动态链接共享库和静态档案库;

/lib这个目录里存放着系统最基本的动态链接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

/proc这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。

/proc 是系统运行时进程和内核的信息存在这里,它属于伪文件系统,存在于内存中。

/tmp 用于用户程序运行时产生的临时文件。

/sys 内核所支持的sysfs文件系统。Sysfs把系统上的设备和总线组织成一个分级的文件,以被用户空间存取。

 

 

3、 交叉编译busybox

busybox的源码可以从http://www.busybox.net/downloads/下载,这里我们下载一个1.5.0版本的源码。

我们在配置busybox的时候是基于默认配置之上来配置的;先make defconfig就是把busybox配置成默认,然后再make menuconfig来配置busybox。

说明:我们在配置一个源代码包之前,可以先阅读源码包目录下的README和INSTALL文件以及Makefile的注释部分,也可以到http://www.busybox.net网站以获取帮助。

http://www.busybox.net/FAQ.html#configure的第二个问题2 How do I configure busybox?有介绍怎么去配置。

 

(1)、在/root/build_rootfs解压

tar -xvf busybox-1.13.3.tgz 

tar xvzf mkyaffs2image.tgz  -C /

cd busybox-1.13.3

(2)、添加交叉工具链

export PATH=/usr/local/arm/4.3.2/bin:$PATH

(3)、配置编译

   make defconfig

make menuconfig

配置时,我们基于默认配置,再配置它为静态编译,安装时不要/usr路径,把MiscellaneousUtilities 下的“taskset”选项去掉,不然会出错。

如下(按Y就会选上,N不选):

手工配置

如果您正在构建一个具有特殊需求的嵌入式设备,那就可以手工使用 menuconfigmake 目标来配置 BusyBox 的内容。如果您熟悉 Linux 内核的编译过程,就会注意到 menuconfig 与配置Linux 内核的内容所使用的目标相同。实际上,它们都采用了相同的基于 ncurses 的应用程序。

使用手工配置,我们可以指定在最终的 BusyBox 映像中包含的命令。我们也可以对 BusyBox 环境进行配置,例如包括对 NSA(美国国家安全代理)的安全增强 Linux(SELinux),指定要使用的编译器(用来在嵌入式环境中进行交叉编译)以及 BusyBox 应该静态编译还是动态编译。图 1 给出了 menuconfig 的主界面。在这里我们应该可以看到可以为 BusyBox 配置的不同类型的应用程序(applet)。

 

Busyboxsetting

           ->builds options

                 ->[*] build busybox as a staticbinarya

           ->installitation options

                 ->[*] don’t use /usr b

MiscellaneousUtilities ―> (c)

           [ ] taskset

其他选项都是一些linux基本命令选项,自己需要哪些命令就编译进去,一般用默认的就可以了。保存退出。

(a)这个选项是一定要选择的,这样才能把busybox编译成静态链接的可执行文件,运行时才独立于其他函数库.否则必需要其他库文件才能运行,在单一个linux内核不能使他正常工作。

(b)这个选项也一定要选,否则make install后,busybox将安装在原系统的/usr下,这将覆盖掉系统原有的命令.选择这个选项后,make install后会在busybox目录下生成一个叫_install的目录,里面有busybox和指向他的链接.

( c)

Taskset命令能够为即将执行的程式或已有进程指定affinity属性,让该程式或进程运行在指定的CPU上。下面是几个例子:
taskset ?c 1 nohup perl pi.pl &    ---指定在1号CPU上执行指定的perl程式
taskset ?c 1 ?P 10284                 ---将10284号进程限定在1号CPU上执行

4、编译安装

Make ARCH=armCROSS_COMPILE=arm-linux-  CONFIG_PREFIX=/root/build_rootfs/rootfs allinstall

(此时bin(195个 290M) sbin(58个 86.4M ---windows下看的结果)已安装了文件,其实是busybox的可执行文件和指向它的链接。不同的链接名完成不同的功能,命令行调用作为一个参数传给busybox,即可完成相应的功能,即于BusyBox 中包含的每个工具来说,都会创建一个符号链接,这样就可以使用这些符号链接来调用 BusyBox 了。BusyBox 然后可以通过 argv[0] 来调用内部工具)

ARCH指定平台

CROSS_COMPILE指定交叉编译

CONFIG_PRRFIX指定安装的路径

5、 copy C库

cp/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/*-a /root/build_rootfs/rootfs/lib/

 

交叉应用程序的开发需要用到交叉编译的链接库,交叉编译的链接库是在交叉工具链的lib目录下;我们在移植应用程序到我们的目标板的时候,需要把交叉编译的链接库也一起移植到目标板上,这里我们用到的交叉工具链的路径是/usr/local/arm/3.3.2/,所以链接库的目录是/usr/local/arm/3.3.2/lib(本来跟目标板相关的目录是/usr/local/arm/3.3.2/arm-linux, 因此要拷贝的链接库应该在/usr/local/arm/3.3.2/arm-linux/lib下,但是此目录的很多链接都是链接到/usr/local/arm/3.3.2/lib目录下的库文件,所以我们从/usr/local/arm/3.3.2/lib目录拷贝库),此目录下有四种类型的文件(其实就2种:.so动态库 .a静态库):

      (1) .so动态库

A、实际的共享链接库(libname-version.so)

      如:libc-2.3.2.so

B、主修订版本的符号链接.(lib.so.version)

程序一旦链接了特定的链接库,它将会使用其符号链接,程序启动时,加载器在加载程序之前,会加载该文件。

           如:libc.so.6

C、与版本无关的符号链接(libname.so)

这些符号链接的只要功能是为需要链接特定的链接库的所有程序提供一个通用的条目,与版本号无关。

      如:libc.so 

(2) .a静态库

静态链接库包文件   

      如:libc.a

6、 建立配置文件

      内核启动的最后,会执行sbin/init程序,init程序在启动的最后会执行/bin/sh,sh在启动的时候会读取文件。

 

(1)在/etc/profile文件里设定PATH,LD_RARYLIB_PATH环境变量,目的是配置用户程序运行的环境。

cd /root/build_rootfs/rootfs/etc

vi profile

内容如下

#!/bin/sh

echo "Set seaech library in/etc/profile"

export LD_LIBRARY_PATH=/lib   #定义查找可用共享对象的位置 //usr/lib

echo "Set user path in/etc/profile"

exportPATH=/bin:/sbin:/usr/bin   #命令的路径

#export PS1=[root@mini2440\\\W]\\$   当有自动补齐功能时使用这个

export PS1=[root@mini2440]\#  # //命令行提示符

保存退出

(2)创建inittab文件,内容如下每一条目用来定义一个子进程,并确定它的启动方法(该文件的):

::sysinit:/etc/init.d/rcS

::respawn:-/bin/sh    (注意:“-”要加上。/bin/sh在/dev/console这个tty上被执行。“-”表示该shell为login shell。

::ctrlaltdel:/bin/umount-a -r

(3)创建/etc/init.d/rcS文件,内容如下(rcS是个可执行的脚步文件,是系统启动之后先执行的命令,所以要确保它可执行 chmod 777 rcS):

(配置的原理了看”busybox的mdev来实现对移动设备的动态挂载功能.mht”)

#!/bin/sh

/bin/mount-a     //“mount -a”命令后将挂载proc,tmpfs、sys 等包含在该文件中的所有的文件系统。

/bin/mount-t sysfs sysfs菜单 /sys //下面4是配置增加热插拔支持

/bin/mount-t tmpfs mdev /dev   ///设置dev 目录被用作一个 tmpfs 文件系统的挂载点,该文件系统是由 mdev 填充的。  这样在/dev目录下就可以看到内核已经挂载的驱动的节点。

/bin/echo/sbin/mdev > /proc/sys/kernel/hotplug  //2)设置内核的hotplug handler 为 mdev, 即当设备热插拔时,由 mdev 接收来自内核的消息并作出相应的回应, 比如挂载U盘。

有热插拔事件产生时,内核就会调用位于/sbin目录的 mdev这时 mdev通过环境变量中的 ACTION 和 DEVPATH, (这两个变量是系统自带的)来确定此次热插拔事件的动作以及影响了/sys 中的那个目录。接着会看看这个目录中是否有“dev”的属性文件,如果有就利用这些信息为 这个设备在/dev 下创建设备节点文件。

mdev -s     //mdev 主要是实现对移动设备的动态挂载 在/dev 目录下建立必要的设备节点   mdev扫描 /sys/class 和/sys/block中所有的类设备目录,如果在目录中含有名为“dev”的文件,且文件中包含的是设备号,则 mdev 就利用这些信息为这个设备在/dev下创建设备节点文件。

 

Mount 、umount、mdev 这些命令都会去读取/etc/fstab文件。

 

(4)在/etc/目录下添加文件fstab,内容如下(该文件定义了文件系统的静态信息):

proc /proc proc defaults 0 0

none /tmp ramfs defaults 0 0

sysfs /sys sysfs defaults 0 0

      则已经挂载的设备可以通过命令查询#lsmod

      所挂载的设备的设备号可查询#cat /proc/devices

   其中/proc 是系统运行时进程和内核的信息存在这里,它属于伪文件系统,存在于内存中。

  /tmp 用于用户程序运行时产生的临时文件。

  /sys 内核所支持的sysfs文件系统。Sysfs把系统上的设备和总线组织成一个分级的文件,以被用户空间存取。

  上面字段的格式及代表的意义:

fs_spec fs_file fs_type fs_options fs_dump fs_pass 

 fs_spec - 该字段定义希望加载的文件系统所在的设备或远程文件系统

fs_file - 该字段描述希望的文件系统加载的目录点

fs_type - 定义文件类型

fs_options - 指定加载该设备的文件系统是需要使用的特定参数选项。大多数系统使用"defaults"就可以满足需要

fs_dump - 该选项被"dump"命令使用来检查一个文件系统应该以多快频率进行转储,若不需要转储就设置该字段为0。

fs_pass - 该字段被fsck命令用来决定在启动时需要被扫描的文件系统的顺序,若该文件系统无需在启动时扫描则设置该字段为0。

保存退出

 

7、构建/dev目录:

cd /root/build_rootfs/rootfs/

mknod dev/console c 5 1   //建立控制台和终端的节点

mknod dev/null  c 1 3

mknod dev/tty1 c 4 1

mknod dev/tty2 c 4 2

mknod dev/tty3 c 4 3

mknod dev/tty4 c 4 4

8、添加一个用户程序

进入工作目录

cd/root/build_rootfs/

编辑源文件

vi hello.c

内容如下

#include<stdio.h>

main()

{

      printf(“hello su\n”);

}

保存退出

 

交叉编译

arm-linux-gcc hello.c –o hello

复制到目标板的根目录

mvhello /root/build_rootfs/rootfs/usr/bin

 

9、设置启动参数,从NFS启动。

setenv bootargs root=/dev/nfs nfsroot=192.169.41.123:/root/build_rootfs/rootfs/ip=192.169.41.23 init=/linuxrc console=ttySAC0,115200 display=sam320

saveenv

reset

 

root=/dev/nfs rw nfsroot=192.168.1.1:/linuxip=192.168.1.5:::255.255.255.0:linux::off

 

该配置为静态IP设置。各参数意义如下:
root=/dev/nfs
:指定根文件系统为 /dev/nfs,即NFS 。这与/dev这个目录并没有什么关系,在此仅为一个名字。
rw
:根文件系统挂载为可读写。还可以有 ro 即只读的选项。
nfsroot=192.168.1.1:/linux
 :指明挂载哪一个NFS上的哪一个目录。这里指的是挂载IP192.168.1.1的电脑上导出的/linux目录。
ip=192.168.1.5:::255.255.255.0:linux::off
:设置本机的IP。此举是为了连接刚才设置的IP。这里是一个静态的配置,配置的格式为 ip=本机的IP地址::网关地址:网络掩码:本机的主机名:网络接口名:off 。一般情况下网关、网络接口名都不需要设置。如果是DHCP获取IP,那很简单,直接 ip=dhcp 即可。

 

9、制作yaffs2映像

cd/root/build_rootfs/

mkyaffs2image-128M  rootfs rootfs.yaffs2

rootfs.yaffs2就是我们要烧写到目标板的映像文件

 

10、烧写rootfs.yaffs2到3分区,启动开发板,运行hello程序。

tftp 30008000 rootfs.yaffs2

nand erase 560000 40000000           3200000(50M)

nand write.yaffs  30008000 560000  61e780 ( 下载完提示下载了多大就多大,是16进制)   61e780

set bootargs 'noinitrd root=/dev/mtdblock3rootfstype=yaffs2 rw console=ttySAC0,115200 init=/linuxrc mem=64M'

saveenv

11、确认内核的信息能挂载到文件系统的proc等目录(如果下面的信息没有则一般是/etc/中的文件写错了)

   #cat /proc/devices  看已经挂载的设备和设备号是否在该文件中

   #ls /dev  看是否有很多设备节点

12、解决rmmod命令不能使用的问题

五、分析inittab文件

Inittab文件中每一行的格式如下:

id:runlevel:action:process

其中:

Id:用来指定所启动进程的控制台,是指入口标识符,它是一个字符串,对于getty或mingetty等其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常工作。在嵌入式系统中一般不添加;

Runlevel:是init所处于的运行级别的标识,一般使用0-6以及S或s。0、1、6运行级别被系统保留:其中0作为shutdown动作,1作为重启至单用户模式,6为重启;S和s意义相同,表示单用户模式,且无需inittab文件,因此也不在inittab中出现,实际上,进入单用户模式时,init直接在控制台(/dev/console)上运行/sbin/sulogin。在一般的系统实现中,都使用了2、3、4、5几个级别,在Redhat系统中,2表示无NFS支持的多用户模式,3表示完全多用户模式(也是最常用的级别),4保留给用户自定义,5表示XDM图形登录方式。7-9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行。 (busybox完全忽略runlevel字段);

# Default runlevel. The runlevels used byRHS 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)

Action:指出init程序在执行相应process时,对process所采取的动作

Process:具体的执行程序;

 

inittab文件的action字段中,有以下action 域可以使用的动作:

l    Sysinit: 为init提供初始化命令行的路径;

l    Respawn:   当该进程死亡时,init将重新启动该进程,不等待该  进程的结束;

l    Askfirst:     当相应的进程终止便重新启动,会t在控制台显示  “Please press Enter to activate this console.”的信息。

l    Wait:          启动进程并等待其结束;

l    Once:         启动相应的进程,但不等待该进程结束;

l    Ctrlaltdel:  当按下Ctrl-Alt-Delete组合键时,执行相应的进程;

l    Shutdown: 当系统关机时,执行相应的进程;

l    Restart:  但init从新启动时,执行相应的进程。

l    boot :在系统引导期间执行本进程. runlevels 域被忽略.

l    off 什么也不做.

l    powerfail 类似 powerwait, 但是init 不等待此进程完成.

l    powerokwait 在 init 收到电源已经恢复的通知后立即执行此进程.

l    powerfailnow 本进程在 init 被告知 UPS 电源快耗尽同时外部电源失败 (无效) 时被执行. (假设 UPS 和监视进程能够发现这样的情况).

 

六、文件系统启动过程

-----------------简单的rootfs的启动过程:

init=/linuxrc是二进制文件 ,而linuxrc是/sbin/init的链接文件,它会去读取配置文件/rootfs/etc里的配置文件 ,然后进入shell控制台。

 

------ 以mini2440文件系统做讲解  su  2011 -06 -27  ------------

1         init=/linuxrc  会去顺序读取配置文件/rootfs/etc里的配置文件inittab 和执行profile.

2   linuxrc是/sbin/init的链接文件。

3   inittab是一个不可执行的文本文件,它有若干行指令所组成。

/etc/inittab  文件中:

 ::sysinit:/etc/init.d/rcS

::respawn:-/bin/sh

::ctrlaltdel:/bin/umount-a -r

4  /etc/init.d/rcS   完成一些系统初始化的工作 ,主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。

#! /bin/sh

/bin/mount -a

/bin/mount -t tmpfs mdev/dev

/bin/echo /sbin/mdev >/proc/sys/kernel/hotplug

mdev -s

其 中:

   Mount 、umount、mdev 这些命令都会去读取/etc/fstab文件。

/bin/mount –a 实际上是把 /etc/fstab 中的设备mount 过去。

(-a     Mountall filesystems (of the given types) mentioned in fstab.)

5  执行/etc/profile/

-------------------------------linux启动过程(/etc/inittab 解读 )---------------------------

第1部分:运行init

init的进程号是1,从这一点就能看出,init进程是系统所有进程的起点,Linux在完成核内引导以后,就开始运行init程序。init程序需要读取配置文件/etc/inittab。inittab是一个不可执行的文本文件,它有若干行指令所组成。在Redhat系统中,inittab的内容如下所示:

# Default runlevel. The runlevelsused 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 havenetworking)

#  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  #运行脚本rc.sysinit

l0:0:wait:/etc/rc.d/rc 0   

l1:1:wait:/etc/rc.d/rc1

l2:2:wait:/etc/rc.d/rc2

l3:3:wait:/etc/rc.d/rc3

l4:4:wait:/etc/rc.d/rc4

l5:5:wait:/etc/rc.d/rc5     #以5为参数运行脚本rc ,并等待其返回,启动守护进程

l6:6:wait:/etc/rc.d/rc6

# TrapCTRL-ALT-DELETE

ca::ctrlaltdel:/sbin/shutdown-t3 -r now   #在启动过程中如果按下ctrlaltdel,将执行/sbin/shutdown

# When our UPS tells us power hasfailed, assume we have a few minutes

# of power left.  Schedule a shutdown for 2 minutes from now.

# Thisdoes, of course, assume you have powerd installed and your

# UPS connected and workingcorrectly. 

pf::powerfail:/sbin/shutdown -f -h+2 "Power Failure; System Shutting Down"

            #如果带UPS电源,则掉电时提示“。。。”,并2min后关机

# If power was restored before theshutdown kicked in, cancel it.

pr:12345:powerokwait:/sbin/shutdown-c "Power Restored; Shutdown Cancelled"

            #如果电源恢复,则提示“。。。”,并取消关机

# Run gettys in standardrunlevels   #init进程打开6个终端,以ttyn为参数执行/sbin/mingetty ,并打开终端用于用户登陆. mingetty程序能打开终端、设置模式。同时它会显示一个文本登录界面。

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:once:/etc/X11/prefdm-nodaemon  #提供图形界面登陆方式

第二部分:系统初始化

在/etc/inittab文件中有这么一行:

  si::sysinit:/etc/rc.d/rc.sysinit

 

  它调用执行了/etc/rc.d/rc.sysinit,而rc.sysinit是一个bash shell的脚本,它主要是完成一些系统初始化的工作,rc.sysinit是每一个运行级别都要首先运行的重要脚本。它主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。

 

  rc.sysinit约有850多行,但是每个单一的功能还是比较简单,而且带有注释,建议有兴趣的用户可以自行阅读自己机器上的该文件,以了解系统初始化所详细情况。由于此文件较长,所以不在本文中列出来,也不做具体的介绍。

 

  当rc.sysinit程序执行完毕后,将返回init继续下一步

第三部分:启动对应运行级别的守护进程

在rc.sysinit执行后,将返回init继续其它的动作,通常接下来会执行到/etc/rc.d/rc程序。以运行级别3为例,init将执行配置文件inittab中的以下这行:

 

  l5:5:wait:/etc/rc.d/rc5

 

  这一行表示以5为参数运行/etc/rc.d/rc,/etc/rc.d/rc是一个Shell脚本,它接受5作为参数,去执行/etc/rc.d/rc5.d/目录下的所有的rc启动脚本,/etc/rc.d/rc5.d/目录中的这些启动脚本实际上都是一些链接文件,而不是真正的rc启动脚本,真正的rc启动脚本实际上都是放在/etc/rc.d/init.d/目录下。而这些rc启动脚本有着类似的用法,它们一般能接受startstoprestartstatus等参数用于控制守护进程

 

  /etc/rc.d/rc5.d/中的rc启动脚本通常是K或S开头的链接文件,对于以S开头的启动脚本,将以start参数来运行。而如果发现存在相应的脚本也存在K打头的链接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先以stop为参数停止这些已经启动了的守护进程,然后再重新运行。这样做是为了保证是当init改变运行级别时,所有相关的守护进程都将重启。

 

  至于在每个运行级中将运行哪些守护进程,用户可以通过chkconfig或setup中的"SystemServices"来自行设定。常见的守护进程有:

 

  amd:自动安装NFS守护进程

  apmd:高级电源管理守护进程

  arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和IP地址对数据库

  autofs:自动安装管理进程automount,与NFS相关,依赖于NIS

  crond:Linux下的计划任务的守护进程

  named:DNS服务器

  netfs:安装NFS、Samba和NetWare网络文件系统

  network:激活已配置网络接口的脚本程序

  nfs:打开NFS服务

  portmap:RPC portmap管理器,它管理基于RPC服务的连接

  sendmail:邮件服务器sendmail

  smb:Samba文件共享/打印服务

  syslog:一个让系统引导时起动syslog和klogd系统日志守候进程的脚本

  xfs:X Window字型服务器,为本地和远程X服务器提供字型集

  Xinetd:支持多种网络服务的核心守护进程,可以管理wuftp、sshd、telnet等服务

 

这些守护进程也启动完成了,rc程序也就执行完了,然后又将返回init继续下一步。

第四部分:建立终端

 

  rc执行完毕后,返回init这时基本系统环境已经设置好了,各种守护进程也已经启动了。init接下来会打开6个终端,以便用户登录系统。通过按Alt+Fn(n对应1-6)可以在这6个终端中切换。在inittab中的以下6行就是定义了6个终端:

 

  1:2345:respawn:/sbin/mingettytty1

  2:2345:respawn:/sbin/mingettytty2

  3:2345:respawn:/sbin/mingettytty3

  4:2345:respawn:/sbin/mingettytty4

  5:2345:respawn:/sbin/mingettytty5

  6:2345:respawn:/sbin/mingettytty6

 

  从上面可以看出在2、3、4、5的运行级别中都将以respawn方式运行mingetty程序,mingetty程序能打开终端、设置模式。同时它会显示一个文本登录界面,这个界面就是我们经常看到的登录界面,在这个登录界面中会提示用户输入用户名,而用户输入的用户将作为参数传给login程序来验证用户的身份。

 

第五部分:登录系统,启动完成

 

  对于运行级别为5的图形方式用户来说,他们的登录是通过一个图形化的登录界面。登录成功后可以直接进入KDE、Gnome等窗口管理器。而本文主要讲的还是文本方式登录的情况:

 

  当我们看到mingetty的登录界面时,我们就可以输入用户名和密码来登录系统了。

 

  Linux的账号验证程序是login,login会接收mingetty传来的用户名作为用户名参数。然后login会对用户名进行分析:如果用户名不是root,且存在/etc/nologin文件,login将输出nologin文件的内容,然后退出。这通常用来系统维护时防止非root用户登录。只有/etc/securetty中登记了的终端才允许root用户登录,如果不存在这个文件,则root可以在任何终端上登录。/etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。

 

  在分析完用户名后,login将搜索/etc/passwd以及/etc/shadow来验证密码以及设置账户的其它信息,比如:主目录是什么、使用何种shell。如果没有指定主目录,将默认为根目录;如果没有指定shell,将默认为/bin/bash。

 

  login程序成功后,会向对应的终端在输出最近一次登录的信息(在/var/log/lastlog中有记录),并检查用户是否有新邮件(在/usr/spool/mail/的对应用户名目录下)。然后开始设置各种环境变量:对于bash来说,系统首先寻找/etc/profile脚本文件,并执行它然后如果用户的主目录中存在.bash_profile文件,就执行它,在这些文件中又可能调用了其它配置文件,所有的配置文件执行后后,各种环境变量也设好了,这时会出现大家熟悉的命令行提示符,到此整个启动过程就结束了。

 

希望通过上面对Linux启动过程的剖析能帮助那些想深入学习Linux用户建立一个相关Linux启动过程的清晰概念,进而可以进一步研究Linux接下来是如何工作的。

 

 

七、附录:linux目录结构

/bin binBinary的缩写。这个目录存放着最经常使用的命令。


/boot这里存放的是启动Linux时使用的一些核心文件,包括一些链接文件以及镜像文件。(BIOS自检->MBR(GRUB)->KERNEL->KERNEL自解压->内核初始化->内核启动)

/dev devDevice(设备)的缩写。该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。

/etc这个目录用来存放所有的系统管理所需要的配置文件和子目录。

/home用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。

/lib这个目录里存放着系统最基本的动态链接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

/lost+found这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。

/mnt在这里面中有四个目录,系统提供这些目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/cdrom上,然后进入该目录就可以查看光驱里的内容了。

/proc这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:

  echo 1> /proc/sys/net/ipv4/icmp_echo_

  ignore_all。

/root该目录为系统管理员,也称作超级权限者的用户主目录。

/sbin s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。

/tmp这个目录是用来存放一些临时文件的。

/usr 我们要用到的很多应用程序和文件几乎都存放在usr目录下。具体来说:

/usr/X11R6存放X-Windows的目录;

/usr/games存放着XteamLinux自带的小游戏;

/usr/bin存放着许多应用程序;

/usr/sbin存放root超级用户使用的管理程序;

/usr/doc Linux技术文档;

/usr/include用来存放Linux下开发和编译应用程序所需要的头文件;

/usr/lib存放一些常用的动态链接共享库和静态档案库;

/usr/local这是提供给一般用户的/usr目录,在这里安装一般的应用软件;

/usr/man帮助文档所在的目录;

/usr/src Linux开放的源代码,就存在这个目录,爱好者们别放过哦;

/var这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。如果你想做一个网站,你也会用到/var/www这个目录。

 

八、文件系统类型介绍

1、Linux支持多种文件系统类型,包括ext2、ext3、vfat、jffs、romfs和nfs等,为了对各类文件系统进行统一管理,Linux引入了虚拟文件系统VFS(Virtual File System),为各类文件系统提供一个统一的应用编程接口。

 

2、文件系统类型

根据存储设备的硬件特性、系统需求,不同的文件系统类型有不同的应用场合。在嵌入式Linux应用中,主要的存储设备为RAM 和FLASH,常用的基于存储设备的文件系统类型包括:jffs2, yaffs, cramfs,ramdisk, ramfs等。

(1)  基于FLASH的文件系统

Flash(闪存)作为嵌入式系统的主要存储媒介,主要有NOR和NAND两种技术。Flash存储器的擦写次数是有限的,NAND闪存还有特殊的硬件接口和读写时序。因此,必须针对Flash的硬件特性设计符合应用要求的文件系统。

((1))NOR FLASH

JFFS:JFFS文件系统最早是由瑞典Axis Communications公司基于Linux2.0内核为嵌入式系统开发的文件系统。

JFFS2:是RedHat公司基于JFFS开发的闪存文件系统,最初是针对RedHat公司的嵌入式产品eCos开发的嵌入式文件系统,所以JFFS2也可以用在Linux,uCLinux。

Jffs2: 日志闪存文件系统版本2 (JournallingFlash FileSystem v2)主要用于NOR型flash,基于MTD驱动层,特点是:可读写、支持数据压缩的日志型文件系统,并提供了崩溃/掉电安全保护等。缺点主要是当文件系统已满或接近满时,因为垃圾收集的关系而使jffs2的运行速度大大放慢。

jffsx不适合用于NAND闪存主要是因为NAND闪存的容量一般较大,这样导致jffs为维护日志节点所占用的内存空间迅速增大。另外,jffsx文件系统在挂载时需要扫描整个FLASH,以找出所有的日志节点,建立文件结构,对于大容量的NAND闪存会耗费大量时间。(新的内核中的NAND FLASH已经支持)

((2))NAND FLASH

yaffs/yaffs2 :(Yet Another Flash FileSystem)是专为NAND型flash而设计的一种日志型文件系统。与jffs2相比,它减少了一些功能(例如不支持数据压缩),所以速度更快,挂载时间很短,对内存的占用较小。另外,它还是跨平台的文件系统,除了Linux和eCos,还支持WinCE, pSOS和ThreadX等。

yaffs与yaffs2的主要区别:前者仅支持小页(512 Bytes) NAND闪存,后者则可支持大页(2KB) NAND闪存。同时,yaffs2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升。

((3))NOR \NAND FLASH

Cramfs:Cramfs是Linux的创始人 Linus 参与开发的一种只读的压缩文件系统,它也基于MTD驱动程序。Cramfs文件系统以压缩方式存储,在运行时解压缩,所有的应用程序要求被拷到RAM里去运行。另外,它的速度快,效率高,其只读的特点有利于保护文件系统免受破坏,提高了系统的可靠性。

2)基于RAM的文件系统

Ramdisk:是将一部分固定大小的内存当作分区来使用。它并非一个实际的文件系统,而是一种将实际的文件系统(如ext2)装入内存的机制。将一些经常被访问而又无需更改的文件通过Ramdisk放在内存中,可以明显地提高系统的性能。但是若ramdisk没有满,已被占用的额外内存也不能用作其他事,若ramdisk满了,其他仍有闲置的内存,也必须重新格式化后才能扩展使用。

Initramfs:也是基于内存的文件系统,它的使用不需要创建内存块设备。增加文件到ramfs(或增大原有的文件)会自动配置更多的内存,并删除或截去文件以释放内存。

NFSNFS (Network File System)是由Sun开发的一种在不同机器之间通过网络共享文件的技术。在嵌入式Linux系统的开发调试阶段,可以利用该技术在主机上建立基于NFS的根文件系统,挂载到嵌入式设备,可以很方便地修改根文件系统的内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值