整体框架:
构建最小根文件系统:
1) 创建设备console和null:
首先,我们需要创建一个目录,自己命名。
这里我创建czg目录:mkdir czg。然后进入自己创建的这个文件夹目录,并创建dev目录:mkdir dev。
进入目录dev:cd dev/ 。
然后我们在Linux系统下查看一下console和null的主次设备号:ls /dev/console /dev/null -l。
这里显示的console的主设备号为5,次设备号为1;null的主设备号为1,次设备号为3。c表示字符设备文件。现在我们就可以创建设备console和null了:
mknod console c 5 1
mknod null c 1 3
2) init ==》 busybox
在安装了busybox的linux下,init等价于busybox。这一步已经自动完成。
安装busybox
cd busybox-1.7.0
make menuconfig
>修改Makefile:CROSS_COMPILE ?= arm-linux-
make
make CONFIG_PREFIX=czg/ install
3) /etc/inittab
在czg目录下创建etc目录:mkdir etc。创建etc目录下的inittab配置文件:vim etc/inittab 。并在其中添加console::askfirst:-/bin/sh 使这个shell的标准输入,标准输出,标准错误都指向这个console。
4)配置第三步指定应用程序
第三步使用的是shell标准输入,linux自带不需要额外配置。
5)配置C库
首先我们创建lib目录,这个目录将用来存放C库的文件:mkdir lib。
进入你存放C库文件的目录下,将C库文件复制到lib目录:cp *.so* /czg/lib -d。
这里用-d将C库中的动态库文件及其链接关系都复制到了czg/lib目录下。这样配置C库也完成了。
完善根文件系统
介绍:mdev的用途主要有两个:初始化/dev目录、动态更新。
动态更新不仅是更新/dev目录,还支持热插拔,即接入、卸下设备时执行某些动作。
其实经过上面的过程,构建了一个最小根文件系统。但如果你生成并烧写到硬件上就会发现,这个小小的根文件系统的确能够正常运行,但它的功能还很有限。为了让它有更加丰富的功能和更方便的使用,现在我们需要添加一些新的配置。
此刻我们制作的根文件系统中有些程序还没有安装,比如ps程序。
有两种方法,一种是在根文件系统启动后我们手动挂载
proc:
mkdir proc
mount -t proc none /proc
这里的proc是linux内核提供的虚拟文件系统。它会将linux系统运行时的信息采集,必须将它挂接到/proc目录下。我们才能使用ps程序。那么经过这样的挂载我们就可以正常使用ps了。下面是在烧写了根文件系统的硬件上执行的命令:
ps
# ps
PID Uid VSZ Stat Command
0 3088 S init
0 SW< [kthreadd]
0 SWN [ksoftirqd/0]
0 SW< [watchdog/0]
0 SW< [events/0]
0 SW< [khelper]
0 SW< [kblockd/0]
0 SW< [ksuspend_usbd]
0 SW< [khubd]
0 SW< [kseriod]
0 SW [pdflush]
0 SW [pdflush]
0 SW< [kswapd0]
0 SW< [aio/0]
0 SW< [mtdblockd]
0 SW< [kmmcd]
0 3092 S -sh
0 3092 R ps
这里我们可以看到有许多进程,其中PID表示的是进程号。ps是用来查看后台进程工作情况的命令。这时,我们进入proc目录,随便打开一个进程查看:
# cd /proc/
# ls
745 diskstats locks sys
75 driver meminfo sysrq-trigger
76 execdomains misc sysvipc
763 fb modules timer_list
771 filesystems mounts tty
asound fs mtd uptime
buddyinfo interrupts net version
bus iomem partitions vmstat
cmdline ioports scsi yaffs
cpu irq self zoneinfo
cpuinfo kallsyms slabinfo
crypto kmsg stat
devices loadavg swaps
# cd 1
# ls -l fd
lrwx------ 1 0 0 64 Jan 1 00:10 0 -> /dev/console
lrwx------ 1 0 0 64 Jan 1 00:10 1 -> /dev/console
lrwx------ 1 0 0 64 Jan 1 00:10 2 -> /dev/console
正如大家看到的,proc/目录下有许多的进程。首列数字与上面的PID号对应,进入PID号,既是进入对应的应用程序。通过” ls -l fd “发现PID为1的进程其标准输入,标准输出,标准错误都指向/dev/console。
这种挂载虚拟文件系统的方法虽然可用,但是十分麻烦,如果不想自己一个一个手动挂载的话,可以在etc/下编写配置文件,统一处理。这样在根文件系统启动的时候,配置文件会帮我们处理好所有程序的文件系统挂载。我们就能直接使用各种程序了。
在etc/inittab中添加::sysinit:/etc/init.d/rcS 。
然后创建rcS这个脚本文件:mkdir etc/init.d => vi etc/init.d/rcS。
在其中输入:mount -t proc none /proc。保存后再给它添加可执行权限:chmod +x etc/init.d/rcS 。
这样修改后的根文件系统就会在启动时为应用程序自动挂载proc,效果和上面手动挂载的一样。
这里我们也可以在rcS文件中添加:mount -a 命令来取代mount -t 命令。mount -a命令是根据etc/fstab来挂载文件的。编写etc/fstab为:proc /proc proc defaults 0 0。其效果和上面相同,为了后续方便统一用mount -a 命令!
由于linux下有很多设备驱动,如果手动一个一个添加dev/目录下的内容十分麻烦,所以我们可以用udev自动添加设备节点。这里我们用到的是busybox下的udev的简化版:mdev。那么我们该如何配置才能使用mdev呢?查看busybox目录下的mdev.txt文件,里面有详细的说明:
Mdev has two primary uses: initial population and dynamic updates. Both
require sysfs support in the kernel and have it mounted at /sys. For dynamic
updates, you also need to have hotplugging enabled in your kernel.
Here's a typical code snippet from the init script:
[1] mount -t sysfs sysfs /sys
[2] echo /bin/mdev > /proc/sys/kernel/hotplug
[3] mdev -s
Of course, a more "full" setup would entail executing this before the previous
code snippet:
[4] mount -t tmpfs mdev /dev
[5] mkdir /dev/pts
[6] mount -t devpts devpts /dev/pts
首先,根据 [1]、[4]我们得知,需要sys目录,dev目录。且需要添加sysfs和tempfs文件类型。所以在etc/fstab中添加:
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
这里从左至右依次代表:设备名、挂载点、文件系统类型、默认参数等。又根据[2]、[3]、[5]、[6]在etc/init.d/rcS中添加:
#! /bin/sh
ifconfig eth0 192.168.2.5 #设置开发板rootfs-ip
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
这里的hotplug表热拔插,指向mdev。当添加新设备时,会调用它来创建新设备节点。而mdev -s则表示把现有的设备节点创建出来。经过这一番更改,我们重新生成根文件系统,烧写到硬件设备上,通过终端观察实验现象:
大家可以看到dev/目录下有很多设备节点,这都是mdev自动创建出来的。
生成yaffs2和jffs2文件
1>yaffs2:
首先我们需要从网络或其他途径获取到mkyaffs2image工具,利用它来生成yaffs2文件。进入存有mkyaffs2image工具的目录下。将它解压缩:
cd /work/system/
tar xjf yaffs_source_util_larger_small_page_nand.tar.bz2
cd Development_util_ok
cd yaffs2/
cd utils/
进入工具目录后:make 。生成我们需要的mkyaffs2image。将它复制:cp mkyaffs2image /usr/local/bin/。并给它可执行权限:chmod +x /usr/local/bin/mkyaffs2image。再次进入我们的czg目录,利用mkyaffs2image生成可烧写的根文件系统:mkyaffs2image ../czg ../czg.yaffs2。
2>jffs2:
生成jffs2比yaffs2要稍稍复杂一些。我这里用到的是”mtd-utils-05.07.23.tar.bz2”,它是MTD设备的工具包,编译它就会生成制作jffs2的工具。它需要zlib压缩包,所以我们要先安装zlib。大家可以自行下载zlib的源码进行安装,这里举例说明:
tar xzf zlib-1.2.3.tar.gz
cd zlib-1.2.3/
./configure --shared --prefix=/usr/
make
make install
这里的shared是编译动态库,prefix表示将zlib安装在哪里。make生成zlib后,make install进行安装。
现在有了zlib后,我们可以编译jffs2的生成工具了。
tar xjf mtd-utils-05.07.23.tar.bz2
cd mtd-util-05.07.23/util
make
make install
现在我们就安装了解压后的jffs2生成工具。进入czg目录,执行:mkfs.jffs2 -n -s 2048 -e 128KiB -d ../czg -o ../czg.jffs2
这里的-n表示不要在每一个擦除块上加上清楚标志;-s 2048表示一页大小为2048字节;-e 128KiB表示一个擦除块大小为128KB;-d 表根文件系统目录;-o表示输出文件。
按理说,执行完这步生成的jffs2烧写到硬件平台上就能够正常运行,但是请大家注意更改自己的bootloader的环境变量,更改为挂载jffs文件类型,而不要默认为yaffs,否则会启动失败。
set bootargs noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0
NFS挂载根文件系统
这里也给大家介绍两种挂载方法:
1.是在已经启动的硬件平台上,将服务器根文件系统挂载到硬件平台上。(推荐)
2.是在未启动的硬件平台上,通过修改环境变量,指定挂载地址为服务器地址,系统一启动就挂载服务器的根文件系统。
挂载的前提是开发板的rootfs能ping通Linux虚拟机,配置过程点我跳转。
1>启动后挂载:
要想用NFS挂载根文件系统,必须满足两个条件:
(1)服务器允许那个目录可被挂接。
(2)硬件平台去挂接那个目录。首先是第一个条件,我们需要到linux系统中 etc/exports里去配置被允许挂接的目录:
vim /etc/exports
在其中添加我们根文件系统所在目录:
/work/nfs_root *(rw,sync,no_root_squash)
/work/nfs_root/czg *(rw,sync,no_root_squash)
保存后,重启NFS服务:/etc/init.d/nfs-kernel-server restart。理论上现在就可以挂载了,我们可以先试验一下,用服务器挂载自己的根文件系统看能否成功:
mount -t nfs 192.168.2.3:/work/nfs_root/czg /mnt
如果系统没有提示出错,而且根文件系统能够正常使用,就说明我们成功了。那么现在来真正的挂载,在已经启动的硬件平台的终端上,我们创建挂载点:mkdir /mnt。然后开始挂载:
mount -t nfs -o nolock 192.168.2.3:/work/nfs_root/czg /mnt
此时,如果挂载成功,在硬件平台上显示的就是服务器的根文件系统了,里面的文件内容一模一样,在服务器上对文件内容的更改也会显示在硬件平台上。
2>启动前挂载:
这里使用的bootloader是u-boot。只需在系统启动时,进入u-boot。修改u-boot的环境变量,使系统的根文件系统地址指向服务器的地址即可。在u-boot下,NFS挂载的定义格式如下:
nfsroot=[:][,]
ip=::::::
所以我们只需根据自己实际的IP地址、网关、子网掩码等替换掉其中的参数,然后将这条命令输给u-boot并保存就可以了。
这里我的rootfs-IP=192.168.2.5;服务器IP=192.168.2.3;网关=192.168.2.1;子网掩码=255.255.255.0 。在u-boot下,输入print就可以看到当前的环境变量,其中和挂载根文件系统相关的是bootargs:
bootargs=noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0
现在根据挂载跟文件系统的格式,我们需要更改:
set bootargs noinitrd root=/dev/nfs nfsroot=192.168.2.3:/work/nfs_root/czg ip=192.168.2.5:192.168.2.3:192.168.2.1:255.255.255.0::eth0:off rootfstype=jffs2 init=/linuxrc console=ttySAC0
将这条环境变量保存,然后启动内核。就可以看到我们的根文件系统和服务器是一样的,也就是说挂载到了服务器的根文件系统上 。