在一个分区上存储文件时,需要遵循一定的格式,这种格式称为文件系统类型,比如ntfs,ext2,yaffs等。除这些拥有实实在在的存储分区的文件系统类型外,Linux还有几种虚拟的文件系统类型,比如proc、sysfs等,他们的文件并不存储在实际的设备上,而是在访问他们是由内核临时生成。
根文件系统目录结构:
1、/bin 目录:
该目录下存放所有用户都可以使用的、基本的命令。这些命令在挂接其他文件系统之前就可以使用。
2、/sbin目录:
该目录下存放系统命令,即只有管理员才能使用的命令,系统命令还可以存放在/usr/sbin、/usr/local/sbin 目录下。/sbin目录找那个存放的是基本的系统命令,他们用于启动系统,修复系统等,也是在挂接其他文件系统之前就可以使用/sbin。不是急需使用的系统命令存放在/usr/bin目录下,本地安装的系统命令存放在/usr/local/sbin目录下。
3、/dev目录:
存放设备文件,可以使用udev机制维护这个目录。
4、/etc目录:
存放各种配置文件,其下的目录和文件都是可选的,他们依赖于系统中所拥有的应用程序,依赖于这些程序是否需要配置文件。
5、/lib目录:
存放共享库和可加载模块(即驱动程序),共享库用于启动系统、运行根文件系统中的可执行程序,比如/bin、/sbin目录下的程序。其他不适根文件系统所必须的库文件可以放在其他目录,比如/usr/lib、/var/lib等。
6、/home目录:用户目录,在/home目录下都有一个普通用户名命名的子目录,存放用户相关的配置文件。
7、/root目录:
8、/usr目录:
9、/var目录:
10、/proc目录:
这是一个空目录,常作为proc文件系统的挂接点,proc文件系统是个虚拟的文件系统,它没有实际的存储设备,里面的目录、文件都是由内核临时生成的,用来表示系统的运行状态,也可以操作其中的文件控制系统。系统启动后,使用以下命令挂接proc文件系统(通常在/etc/fstab进行设置以自动挂接)。
mount -t proc none /proc
11、/mnt目录:
12、/tmp目录:
一些需要生产临时文件的程序要用到/tmp目录,所以/tmp目录必须存在,并且可以访问。
init进程介绍及用户程序启动过程:
init进程是由内核启动的第一个(也是唯一的一个)用户进程(进程ID为1),它根据配置文件决定启动哪些程序,比如执行某些脚本、启动shell、运行用户指定的程序等。init进程是后续所有进程的发起者,比如init进程启动/bin/sh程序后,才能够在控制台上输入各种命令。
init进程的执行程序通常是/sbin/init,上面讲述的init进程的作用只不过是/sbin/init这个程序的功能。我们完全可以编写自己的/sbin/init程序,或者传入命令行参数"init =xxx"指定某个程序作为init程序运行。 通常使用busybox集成的init程序。
busybox init进程的启动子进程:(其源代码在init/init.c文件中)。
如果存在/etc/inittab文件,busybox init 程序解析它,然后按照他的指示创建各种子进程,否则使用默认的配置创建子进程。
/etc/inittab 文件中每个条目用来定义一个子进程,并确定他的启动方法,格式如下:
对于busybox init进程,上述各个字段作用如下:
1、
2、
3、
sysinit 系统启动后最先执行
wait 执行完sysinit类进程后执行
once
respawn
askfirst
shutdown
restart
4、
在/etc/inittab 文件的控制下,init进程的行为总结如下:
a、在系统启动前期,init进程首先启动
b、在系统正常运行期间,init进程首先启动
c、在系统退时,执行
如果根文件系统中没有/etc/inittab 文件,busybox init程序将使用如下默认的inittab条目:
::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
tty2::askfirst:/bin/sh
tty3::askfirst:/bin/sh
tty4::askfirst:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
::restart:/sbin/init
/etc/inittab实例:
放在busybox 的exampes/intitab 文件,创建一个inittab,内容如下:
#/etc/inittab
#这是init进程启动的第一个子进程,它是一个脚本,可以在里面指定用户想执行的操作
#比如挂接其他文件系统,配置网络等
::sysinit:/etc/init.d/rcS
#启动shell,以/dev/ttySAC0作为控制台
ttySAC0::askfirst:-/bin/sh
#按下Ctrl + Alt +Del 之后执行的程序,不过在串口控制台中无法输入 Ctrl + Alt +Del组合键
::ctrlaltdel:/sbin/reboot
#重启、关机前执行的程序
::shutdown:/bin/umount -a -r
移植busybox:
busybox将众多的UNIX命令集合进一个很小的可执行程序中,其按模块进行设计,可以很容易地加入、去除某些命令,或增减命令的某些选项。使用busybox创建最小根文件系统时,只需要在/dev目录下创建必要的设备节点、在/etc目录下创建一些配置 文件就可以了,如果busybox使用动态连接,还要在/lib目录下包含库文件。
编译、安装busybox:
一、下载,解压busybox:
tar xjf busybox-1.7.0.tar.bz2
busybox集合了几百个命令,在一般系统中并不需要全部使用,可以通过配置busybox 来选择这些命令,定制某些命令的功能(选项)、指定busybox的连接方法(动态链接还是静态链接)、指定busybox的安装路径。
二、配置busybox,在busybox-1.7.0目录下执行"make menuconfig"命令即可进入配置界面:
使用默认配置,执行"make menuconfig"后退出,保存配置即可。
busybox常用配置选项:
1、busybox的性能微调。
设置TAB键补全:
Busybox Settings--->
Busybox Library Tuning --->
[*] Tab competion
2、连接/编译选项。
指定是否使用静态连接:
Build Options --->
[ ] Build BusyBox as a static binary (no shared libs)
使用glibs时,如果静态编译busybox会提示以下警告信息,表示会出现一些莫名其妙的问题。
#warning static linking against glibs produces buggy executables
所以使用动态连接的busybox,在构造根文件系统是需要在/lib目录下方直glibs库文件。
3、Archival Utilities选项。
选择tar命令:
Archival Utilities --->
[*] tar
4、Linux Module Utilites选项。
要使用可加载模块,Linux Module Utilities下面的配置要选上.
Linux Module Utilities --->
[*]
[*]
...
5、Linux System Utilities 选项。
支持mdev,这可以很方便的构造/dev目录,并且可以支持热拔插设别,另外为方便调试,选中mount、umount命令,并让mount命令支持NFS(网络文件系统)。
Linux System Utilities --->
[*] mdev
[*] Support /etc/mdev.conf
[*] Support command execution as device addition/removal
[*] mount
[*] Supprot mounting NFS file systems
[*] umount
[*] umonut -a option
6、Networing Utilities选项
增加ifconfig命令:
Networking Utilities --->
[*] ifconfig
三、编译和安装busybox:
a.修改busybox根目录的Makefile,使用交叉编译器:
修改为:
175 ARCH ?= arm
176 CROSS_COMPILE ?= arm-linux-
b.执行“make”命令编译busybox。
c.安装,执行“make CONFIG_PREFIX = dir_name install ,就可以将busybox安装在dir_name指定的目录下。
在安装目录下会生成如下文件、目录:(如安装目录/work/nfs_root/fs_mini)
bin
linuxrc -> bin/busybox //(uboot启动参数就是 init=linuxrc)
sbin
usr
其中Linuxrc和上面分析的/sbin/init程序的功能完全一样,其他目录下是各种命令,不过他们都是到/bin/busybox的符号链接,比如 安装目录下的 sbin 目录下/work/nfs_root/fs_mini/sbin的命令:
halt -> ../bin/busybox
ifconfig -> ../bin/busybox
...
除bin/busybox外,其他文件都是到bin/busybox的符号链接。
使用glibc库:
参考制作交叉编译工具链,若已制作交叉编译工具链,则已经生成了glibc库,可以直接使用它来构建根文件系统。
glibc库的组成:
glibc库的位置是/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib,里面的目录,文件可以分为7类:
1.加载器ld-2.3.6.so,ld-linux.so.2,动态程序启动前,他们被用来加载动态库。
2.目标文件(.o)。比如crtl.o crti.o等,在生成应用程序时,这些文件像一般的目标文件一样被连接。
3.静态库文件(.a)。比如静态数学库libm.a、静态C++库 libstdc++.a等,编译静态程序时会连接他们。
4.动态库文件(.so、.so.[0-9]*)。他们可能是一个连接文件,编译动态库时会用到这些文件,但是不会连接他们,运行时才连接。
5.libtool库文件(.la).
6.ldscripts目录。里面是各种连接脚本,在编译应用程序时,他们被用于指定程序的运行地址、各段的位置等。
7.其他目录及文件。
安装glibc库:
在开发板上只需啊哟加载器和动态库,假设要构建的根文件系统目录为/work/nfs_root/fs_mini,操作如下:
$ mkdir -p /work/nfs_root/fs_mini/lib
$ cd /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib
$ cp *.so* /work/nfs_root/fs_mini/lib -d
上面复制的库文件不是每一个都会被用到,可以根据应用程序对库的依赖关系保留要用到的,可以通过ldd命令查看一个程序会用到哪些库,主机自带的ldd命令不能查看价差编译出来的程序,有一下两种代替的方法:
1、如果有uClibc-0.9.28的代码,可以进入utils子目录生成ldd.host工具。
$ cd uClibc-0.9.28/utils
$ make ldd.host
然后将生成的ldd.host放到主机/usr/local/bin目录下即可使用。比如对于动态连接的Uusybox,他的库依赖关系如下:
$ ldd.host busybox
libcrypt.so.1 => /lib/libcrypt.so.1 (0x00000000)
libm.so.6 => /lib/libm.so.6 (0x00000000)
libc.so.6 => /lib/libc.so.6 (0x00000000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00000000)
折表示busybox要使用的库文件有libcrypt.so.1 、libm.so.6 、libc.so.6,加载器为/lib/ld-linux.so.2,主机上没有对应的文件没关系,开发板的根文件系统上有就行。
2、可以使用下面的命令:
$ arm-linux-readelf -a "your binary" | grep "Shared",
比如对于动态连接的busybox:
$ arm-linux-readelf -a ./busybox | grep "Shared"(与上面相比,少了加载器,但要依赖加载器)
构建根文件系统:
上面两节介绍了编译安装busybox、C库,建立了bin/, sbin/, sur/bin/ ,sur/sbin/, linuxrc,lib/等目录 (busybox安装完的时候就有了bin sbin linuxrc user目录)。
接下来介绍余下目录的建立。假设开发板根文件系统在主机上的目录为/works/nfs_root/fs_mini。
一、构建etc目录:
init进程根据/etc/inittab 文件来创建其他子程序,比如调用脚本文件配置IP地址,挂接其他文件系统,最后启动shell等。
这里要创建3个文件:etc/inittab, etc/init.d/rcS, etc/fstab
1.创建etc/inittab文件
在/work/nfs_root/fs_mini/etc 目录下创建一个inittab文件,内容如下:
# /etc/inittab
::sysinit:/etc/init.d/rcS
ttySAC0::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
2、创建ect/init.d/rcS文件
这是一个脚本文件,可以在里面添加想自动执行的命令,以下命令配置IP地址,挂接/etc/fstab指定的文件系统
#!/bin/sh
ifconfig eth0 192.168.1.17
mount -a
第一行表示这是一个脚本文件,运行时使用/bin/sh解析。
第二行用来配置IP地址。
第三行挂接/etc/fstab文件指定的所有文件系统。
要改变这个文件的属性,使它能够执行:
chmod +x etc/init.d/rcS
3、创建etc/fstab文件
内容如下,表示执行mount -a 命令后将挂接proc tmpfs 文件系统。
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
/etc/fstab 文件被用来定义文件系统的静态信息,这些信息被用来控制mount 命令的行为,文件中个字段的意义如下:
1.device:要挂载的设备
比如/dev/hda2 /dev/mtdblock1 等设备文件,也可以是其他格式,比如对于proc文件系统,这个字段没有意义,可以是任 意值;对于NFS文件系统,这个字段为
2.mount-point:挂接点
3.type:文件系统类型。
比如proc,jffs2,nfs等,也可以是auto,表示自动检测文件系统类型。
4.option:挂接参数,以逗号隔开。
/etc/fstab的作用不仅仅是用来控制mount -a 的行为,即使是一般的mount命令也受它控制,其他常用挂接参数:
参数名 说明 默认值
auto/noauto 决定执行mount-a时是否自动挂接 auto
user/nouser user:允许普通用户挂接 nouser:只允许root用户挂接 nouser
exec/noexec 决定是否允许运行所挂接的设备上的程序 exec
Ro 以只读方式挂接 --
rw 以读写方式挂接 --
sync/async 修改文件的时候,是否同步写入设备中 sync
defaults rw、suid、dev、exec、auto、nouser、async等的组合 --
5、dump和fsck order:用来决定控制dump、fsck程序的行为。
//inittab 调用rcS,rcS里面mount fstab里面的文件系统,inittab 和fstab的内容都是有固定格式的,rcS是脚本。
二、 构建dev目录:
有两种方法构建dev目录
1、静态创建设备文件。
从系统的启动过程可知,涉及的设备文件又:/dev/mtdblock*(MTD块设备)、/dev/ttySAC*(串口设备)、
/dev/console、/dev/null,只要建立以下设备就可以启动系统。
$ mkdir -p /work/nfs_root/fs_mini/dev
$ cd /work/nfs_root/fs_mini/dev
$ sudo mknod console c 5 1
$ sudo mknod null c 1 3
$ sudo mknod ttySAC0 c 204 64 //一般系统中ttySAC0主设备号为4,但2440 2410中是204
$ sudo mknod mtdblock0 b 31 0
$ sudo mknod mtdblock0 b 31 1
$ sudo mknod mtdblock0 b 31 2
其他设备文件可以当系统启动后,使用cat /proc/devices 命令查看内核中注册了那些设备,然后一一创建相应的设备文件。
2、使用mdev创建设备文件。
mdev是udev的简化版本,它也是通过读取内核信息来创建设别文件。mdev的用途主要有两个:初始化/dev目录、动态更新/dev目录,和热拔插。要使用mdev,需要内核支持sysfs文件系统,为了减少对flash的读写,还要支持tmpfs文件系统。先确保
内核已经设置了CONFIG_SYSFS、CONFIG_TMPFS配置项。
mdev相关命令:
mount -t tmpfs mdev /dev //使用内存文件系统,减少对Flash的读写
mkdir /dev/pts //devpts用来支持外部网络连接(telnet)的虚拟终端
mount -t devpts devpts /dev/pts
mount -t sysfs sysfs /sys //mdev通过sysfs文件系统获得设备信息
echo /bin/mdev>/proc/sys/kernel/hotplug //设置内核,当有设备拔插时调用/bin/mdev程序
mdev -s //在/dev目录下生产内核支持的所有设备的结点
要在内核启动时自动运行mdev,需要修改/work/nfs_root/fs_mini中的两个文件:etc/fstab和etc/init.d/rcS。
修改etc/fstab添加3个文件系统,使得后面可以自动挂载,即相当自动执行mount -t tmpfs mdev /dev ;
mount -t devpts devpts /dev/pts;mount -t sysfs sysfs /sys 3条命令。
添加的内容:
# device mount-point type options dump fsck order
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
修改etc/init.d/rcS,加入下面几行,以自动运行他们:
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
在使用mdev构造dev目录之前,还要建立两个设备文件:dev/console、/dev/null。
构建其他目录:
其他目录可以是空目录,比如proc、mnt、tmp、sys、root等,创建他们。
这样一个小小的根文件系统就建立好了,开发板可以通过NFS挂接到这里来作为根文件系统启动。如果不想挂接,可以利用这个根文件系统和制作映像文件的工具(如mkyaffsimage)制作一个映像文件,烧写到开发板,作为开发板的根文件系统。