被围观了 18,940 次

如果没有用于存放应用程序和系统配置文件的根文件系统,那么Linux内核几乎没有什么用途。根文件系统存在的形式有多种:通过NFS挂载的根、基于RAMDISK的根和烧写在FLASH中的根。关于创建这种类型的根文件系统的文档在Internet网上随处可见,但是大多数都是管中窥豹——片面。本文将较系统地介绍如何创建一个简单的嵌入式根文件系统,包括:通过NFS挂载的根、RAMDISK根、JFFS2类型的根和只读根(CRAMFS)

1、引言

这里采用busybox工具来做根,busybox具有“瑞士军刀”的美称,采用它制作的根具有绝大多数常用的命令,但是总的大小又非常有限(不超过2兆)————其实编译之后也只有一个命令busybox,其他的命令都是指向它的一个符号链接文件,比如ls命令,就是通过命令“ls -s /bin/busybox /bin/ls“创建的符合链接文件。同时busybox是可灵活配置的,通过菜单点菜的方式来选择需要的命令。

本文后续章节安排如下:
1、下载和编译busybox;
2、通过NFS挂载根文件系统;
3、编译和测试基于RAMDISK的根;
4、编译和测试JFSS2类型的根;
5、编译和测试CRAMFS类型的只读根;

假定条件:你需要超级用户权限;busybox和指向它的所有链接的文件主人和组都是root,因为嵌入式设备启动时一般只有一个用户,那就是root。

工作目录结构:
/usr/local/arm/tars存放源代码包;
/usr/local/arm/source存放解压之后的源码目录;
/usr/local/arm/BUILD/busybox存放编译后的程序;
/usr/local/arm/BUILD/rootfs制作的根文件系统目录;
/srv/rootfs通过nfs输出的根,开发箱就是Mount这个目录;
采用下面的方法创建这些目录:
mkdir -p /usr/local/arm/{tars,source,BUILD/busybox, BUILD/rootfs}

2、配置内核以支持相应的文件系统

对于本文中将要创建的文件系统类型,我们必须要配置内核来支持它们(通过命令make menuconfig配置内核),具体的配置参见下文。

2.1、配置内核支持从NFS挂载根文件系统

在嵌入式软件开发和调试过程中,根文件系统往往驻留在电脑上,开发板通过NFS临时挂载过去,这时的内核需要配置支持从NFS挂载根:

make menuconfig-->File systems-->Network file systems-->选中NFS file system support,Provide NFSv3 client support, Provide NFSv4 client support和Root file system on NFS

注意:不同的内核版本,配置菜单可能不一样,可以采用搜索方法定位菜单,如在配置菜单里输入/NFS搜索NFS的菜单项。

2.2、配置内核支持从RAMDISK根文件系统

在配置u-boot时,我们会下载一个根文件镜像到内存,并且传递参数给内核,告诉内核根文件系统在RAMDISK中的位置和大小。让内核支持RAMDISK的配置如下:

make menuconfig-->Device Drivers-->Block devices-->RAM disk support-->Default RAM disk size[16384],即一个RAMDISK为16兆
make menuconfig-->General setup-->Initial RAM filesystem and RAM disk(initramfs/initrd) support

2.3、配置内核支持MTD

为了使用基于flash的文件系统,比如jfss2/cramfs等,必须引入MTD层。让内核支持MTD的配置如下:

make menuconfig-->Device Drivers-->Memory Technology Devices (MTD) support-->选中相应的其他项。

配置内核支持MTD涉及很多配置项,需要仔细微调。

2.4、配置内核支持Flash文件系统(JFFS2和CRAMFS)

JFFS2是第2版日志闪存文件系统,主要用于NOR型闪存,基于MTD块设备。特点是可读写的、支持数据压缩的、基于哈希表的日志型文件系统,并具有崩溃/掉电安全保护,提供“写平衡”支持等。缺点主要是当文件系统已满或接近满时,因为垃圾收集的关系而使jffs2的运行速度大大放慢,不适合大容量NAND闪存。CRAMFS是一种基于MTD块设备的只读压缩文件系统,速度快,效率高,其只读的特点有利于保护文件系统免受破坏,但不支持就地执行(XIP)。

make menuconfig-->File systems-->Miscellaneous filesystems-->Journalling Flash File System v2 (JFFS2) support, JFFS2 write-buffering support, Advanced compression options for JFFS2, JFFS2 ZLIB compression support,JFFs2 RTIME compression support, Compressed ROM file system support(cramfs)

3、下载和编译busybox

3.1、准备源码:

# cd /usr/local/arm/tars
# wget http://www.busybox.net/downloads/busybox-1.16.0.tar.bz2
# cd /usr/local/arm/source && tar -xjf busybox-1.16.0.tar.bz2
# cd busybox-1.16.0

3.2、配置和编译:

# apt-get install libncurses5-dev ---下面的命令需要用到curses.h头文件,而这个文件包含在libncurses5-dev软件包里,所以先要安装这个软件包。
# mkdir /usr/local/arm/source/BUILD/busybox-1.16.0
# make  O=../BUILD/busybox-1.16.0  menuconfig

Busybox Settings
  General Configuration
     Show terse applet usage messages
     Store applet usage messages in compressed form
     Use the devpts filesystem for Unix98 PTYs
     (/proc/self/exe) Path to BusyBox executable
  Build Options
     Build BusyBox as a static binary (no shared libs)
     Do you want to build BusyBox with a Cross Compiler
     (arm-linux-) Cross Compiler prefix
  Installation Options
     (/srv/rootfs) BusyBox installation prefix
  Coreutils
     basename
     cat
     chmod
     cp
     cut
     echo
     false
     head
     hostid
     ln
     ls
     mkdir
     mkfifo
     mknod
     mv
     pwd
     rm
     sync
     tail
     touch
     true
     uname
     yes
  Console Utilities
     clear
     reset
  Editors
     awk
     sed
     vi
  Finding Utilities
     find
     grep
  Init Utilities
     init (keep the defaults that come with this selection)
     Support running commands with a controlling-tty
     poweroff, halt, and reboot
     mesg
  Login/Password Management Utilities
     Use internal password and group functuions
     getty
     login
       (de-select Support for /etc/securetty)
  Linux Module Utilities
     insmod
     rmmod
     lsmod
     modprobe
     Support version 2.6.x Linux kernels
  Linux System Utilities
     dmesg
     mdev
     Support /etc/mdev.conf
     Support command execution at device addition/removal
     mkswap
     more
     mount
     swaponoff
     umount
     umount –a option
  Networking Utilities
     hostname
     ifconfig
     ping
     telnet
     telnetd
 Process Utilities
     kill
     killall
     pidof
     ps
  Shells
     ash (keep all the defaults)
     Expand prompt string
     ---Bourne Shell Options
        Command line editing
        History saving
        Tab completion
        Fancy shell prompts
  System Logging Utilities
     syslogd
     klogd

注意:上面列出来的是我们常用的命令,当然您可以添加更多的命令
# make  O=../BUILD/busybox-1.16.0  
# make  O=../BUILD/busybox-1.16.0  install

清点我们的战果:
# cd /srv/rootfs  && ls -la

总计 20d
rwxr-xr-x 5 root root 4096 2011-05-31 20:29 .
drwxr-xr-x 8 root root 4096 2011-05-31 20:29 ..
drwxr-xr-x 2 root root 4096 2011-05-31 20:29 bin
lrwxrwxrwx 1 root root   11 2011-05-31 20:29 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 2011-05-31 20:29 sbin
drwxr-xr-x 4 root root 4096 2011-05-31 20:29 usr

进入bin和sbin目录,可以看到更多的命令(这些命令都是指向busybox的符号链接),继续采用下面的命令来看看到目前为止整个根的大小(应该不会超过2.5兆):
# du -sh /srv/rootfs

4、制作根

4.1、创建需要的目录:

# mkdir -p /srv/rootfs && cd /srv/rootfs/
# mkdir -p dev dev/ptf etc etc/init.d lib mnt opt proc root sys tmp var var/log
mknod dev/console c 5 1
# mkdir debugfs   ---从2.6.11版本开始,引入了debugfs文件系统,因此可以创建一个目录debugfs,用于挂在debugfs文件系统。

4.2、创建需要的配置文件

1)、为了使得/proc和/dev/pts目录在系统启动时自动挂载文件系统,我们需要编写文件/etc/fstab
# cd etc
# vim fstab
proc            /proc           proc    defaults        0 0
none            /dev/pts        devpts  mode=0622       0 0

2)、用户登录时需要用到passwd,group,hosts文件,分别定义如下:
# vim group
root:x:0:root
# vim passwd
root::0:0:root:/root:/bin/ash
# vim hosts
127.0.0.1       localhost

内核初始化之后首先启动/sbin/init进程,而这个进程首先会读取/etc/inittab文件,根据这个文件来执行一些列的操作,我们的inittab内容如下:
# vim inittab
::sysinit:/etc/init.d/rcS
# /bin/ash
#
# Start an "askfirst" shell on the serial port
ttyS0::askfirst:-/bin/ash
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

------------------------------------------------------------------------
小贴士:
inittab文件每一行告诉init进程执行一个命令,一行的格式是id:runlevel:action:process,其中action定义如下:

  • sysinit:init初始化命令脚本文件
  • respawn:进程终止时重新启动
  • askfirst:重启进程前先询问
  • wait:等待进程执行完毕后,init才继续执行
  • shutdown:关机时执行相应的进程
  • restart:重启时执行,通常是执行init
  • Once:执行进程一次,且init不等待进程返回

init会不断扫描inittab文件,根据每一行的action先后执行对应的process,action的优先级为:sysinit --> wait --> once --> respawn --> askfirst
----------------------------------------------------------------------------

由上面的inittab文件我们知道,sysinit对应的操作会首先执行,即首先/etc/init.d/rcS:
# vim init.d/rcS

#!/bin/sh
#   ---------------------------------------------
#   Common settings
#   ---------------------------------------------
HOSTNAME=XSCALE270
VERSION=1.0.0

hostname $HOSTNAME

#   ---------------------------------------------
#   Prints execution status.
#
#   arg1 : Execution status
#   arg2 : Continue (0) or Abort (1) on error
#   ---------------------------------------------
status ()
{
       if [ $1 -eq 0 ] ; then
               echo "[SUCCESS]"
       else
               echo "[FAILED]"

               if [ $2 -eq 1 ] ; then
                       echo "... System init aborted."
                       exit 1
               fi
       fi

}

#   ---------------------------------------------
#   Get verbose
#   ---------------------------------------------
echo ""
echo "    System initialization..."
echo ""
echo "    Hostname       : $HOSTNAME"
echo "    Filesystem     : v$VERSION"
echo ""
echo ""
echo "    Kernel release : `uname -s` `uname -r`"
echo "    Kernel version : `uname -v`"
echo ""

#   ---------------------------------------------
#   MDEV Support
#   (Requires sysfs support in the kernel)
#   ---------------------------------------------
echo -n " Mounting /proc             : "
mount -n -t proc /proc /proc
status $? 1

echo -n " Mounting /sys              : "
mount -n -t sysfs sysfs /sys
status $? 1

echo -n " Mounting /dev              : "
#mount -n -t tmpfs -o mode=0755 udev /dev
/bin/mount -t tmpfs tmpfs /dev
status $? 1

echo "Starting udevd..."
#cp -a -f /lib/udev/devices/* /dev
echo "" > /proc/sys/kernel/hotplug
/sbin/udevd --daemon
status $? 0

/bin/udevstart
status $? 1

#   ---------------------------------------------
#   Disable power management
#   (Requires sysfs support in the kernel)
#   ---------------------------------------------
echo -n " Disabling Power mgmt       : "
echo -n "1" > /sys/power/cpuidle_deepest_state
status $? 1

#   ---------------------------------------------
#   Turn off LCD after 1 hour of inactivity
#   (Requires sysfs support in the kernel)
#   ---------------------------------------------
echo -n " Turn off LCD after 1 hour  : "
echo -n "3600" > /sys/power/fb_timeout_value
status $? 1

#   ---------------------------------------------
#   Mount the default file systems
#   ---------------------------------------------
echo -n " Mounting other filesystems : "
mount -a
status $? 0

#   ---------------------------------------------
#   Set PATH
#   ---------------------------------------------
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin

#   ---------------------------------------------
#   Start other daemons
#   ---------------------------------------------
echo -n " Starting syslogd           : "
/sbin/syslogd
status $? 0

echo -n " Starting sshd           : "
/usr/sbin/sshd
status $? 0

#   ---------------------------------------------
#   Done!
#   ---------------------------------------------
echo ""
echo "System initialization complete."

#   ---------------------------------------------
#   Start demo app
#   ---------------------------------------------
#if [[ -x /etc/init.d/demo_start ]]; then
#       echo " Starting Demo Application..."
#       /etc/init.d/demo_start &
#       sleep 5
#fi

为了在启动时自动挂载debugfs到debug目录,下面的代码可以加到rcS脚本的末尾。不过debugfs需要内核的支持(make menuconfig --> Kernel Hacking --> Debug Filesystem)

cat /proc/filesystems | grep -q debugfs
if [ $? -eq 0 ] ; then
        echo -n " Mounting /debug             : "
        mount -n -t debugfs none /debug
        status $? 1
fi

 

chmod 755 init.d/rcS ---这样脚本就可以执行了

4.3、创建需要到设备文件:

cd  /srv/rootfs/dev
mknod -m 444 console c 5 1
mknod -m 444 dsp c 14 3
mknod -m 444 fb0 c 29 0
mknod -m 444 fb1 c 29 32
mknod -m 444 keypad c 251 0

mknod -m 444 kmem c 1 2
mknod -m 444 mem c 1 1
mknod -m 444 mixer c 14 0
mknod -m 444 mtdblock3 b 31 3
mknod -m 444 mtdr3 c 90 7
mknod -m 444 mtd3 c 90 6
mknod -m 444 null c 1 3

mknod -m 444 ram0 b 1 0
mknod -m 444 ram1 b 1 1
mknod -m 666 random c 1 8
mknod -m 444 rom0 b 31 0
mknod -m 444 rom1 b 31 1
mknod -m 444 rtc c 250 0
mknod -m 444 ts c 11 0
mknod -m 444 tty c 5 0
mknod -m 444 tty0 c 4 0
mknod -m 444 tty1 c 4 1

mknod -m 444 ttyS0 c 4 64
mknod -m 444 ttyS1 c 4 65

mkdir touchscreen && cd touchscreen
mknod -m 644 ucb1x00 c 10 14

cd ..
ln -s fb0 fb
ln -s ram0 root

 

 

 

 

 

4.3、关于设备节点文件:

根文件系统下的/dev目录存放了全部的设备节点文件————这些特殊的文件提供了应用程序访问设备的入口,比如串口COM1对应/dev/ttyS0,串口COM2对应/dev/ttyS1。应用程序可以“打开/读/写/关闭”设备文件来访问相应的设备。那么现在的问题是对于我们即将要制作的根文件系统,到底要创建哪些设备文件而哪些设备文件又不要创建呢?

对于设备文件的创建,Linux先后经历了三个阶段,从最早(2.4以前的版本)的静态创建(例如利用命令mknod -m 444 /dev/ttyS0 c 4 64 创建一个串口1设备文件),到2.4.x引入设备文件系统devfs,再到现在的采用用户空间工具udev。不管怎么说,总的目标是创建必要的设备文件,不多也不少。之所以现在发展到udev,自然有它的优越性,但是对于嵌入式产品,集成的设备一般是固定不变的,所以很多嵌入式开发者倾向于采用命令静态创建设备文件,但是随着嵌入式产品的智能化越来越高和热插拔配件越来越多,采用udev是一个一劳永逸之策。

内核2.4.x开始引入了devfs文件系统。设备驱动模块装载的时候会向devfs文件系统注册,此时操作系统自动创建对应的设备节点文件。这个同样会导致其他问题(例如存在不确定的设备映射,有时一个设备映射的设备文件可能不同,例如我的U盘可能对应sda有可能对应sdb;再比如没有足够的主/辅设备号,当设备过多的时候,显然这会成为一个问题;还有/dev目录下文件太多而且不能表示当前系统上的实际设备以及命名不够灵活,不能任意指定等等)。

所以从2.6.13开始就不再使用devfs了。(2.6.15内核版本开始)目前取代他的是udev——个用户空间程序,目前很多的Linux分发版本采纳了udev的方式,因为它在Linux设备访问,特别是那些对设备有极端需求的站点(比如需要控制上千个硬盘)和热插拔 设备(比如USB摄像头和MP3播放器)上具有优势。

udev需要内核sysfs和tmpfs的支持,sysfs为udev提供设备入口和uevent通道,tmpfs为udev设备文件提供存放空间。sysfs文件系统挂载到/sys上,它跟devfs一样它也是一个虚拟文件系统,也是用来对系统的设备进行管理的,它把实际连接到系统上的设备和总线组织成一个分级的文件,用户空间的程序同样可以利用这些信息以实现和内核的交互。用户空间的工具udev就是利用了sysfs提供的信息(主要是event文件,对该文件的“写”会送出设备事件)和udev配置文件来实现所有devfs的功能的,但不同的是udev运行在用户空间中,而devfs却运行在内核空间,而且udev不存在devfs那些先天的缺陷。Udev工具能够根据系统中的硬件设备的状况动态更新设备文件,包括设备文件的创建,删除等,设备文件通常放在/dev目录下,使用udev后,在/dev下面只包含系统中真实存在的设备。

当设备驱动注册到sysfs文件系统时,内核会通过netlink向udevd守护进程发送udev(设备)事件,然后udevd把事件传递给用户空间的udev,最后由udev根据配置规则创建相应的设备节点文件。

注意:在上电之前系统上是没有足够的设备文件可用的,我们需要一些技巧让kernel先引导起来。由于在kernel启动未完成以前我们的设备文件不可用,如果使用mtd设备作为rootfs的挂载点,这个时候/dev/mtdblock 是不存在的,我们无法让kernel找到rootfs,kernel只好停在那里惊慌。这个问题我们可以通过给kernel传递设备号的方式来解决,在linux系统中,mtdblock的主设备号是31,part号从0开始,那么以前的/dev/mtdblock/3就等同于31:3,以次类推,所以我们只需要修改bootloader传给kernel的cmd line参数,使root=31:3,就可以让kernel在udevd未起来之前成功的找到rootfs。

下面我们一步一步来建立udev机制。

1)、编译安装udev

# cd /usr/local/arm/tars
# wget https://www.kernel.org/pub/linux/utils/kernel/hotplug/udev-174.tar.bz2
# cd /usr/local/arm/source
# tar -jxf ../tars/udev-174.tar.bz2
# cd udev-174
# make CROSS_COMPILE=arm-linux-
# cp udevd /srv/rootfs/sbin/
# cp udevstart /srv/rootfs/sbin/

编译会产生很多课执行程序,比如test-udev,udevcontrol,udevd,udevinfo udevmonitor,udevstart,udevsettle,udevtest,udevtrigger,在嵌入式系统我们只要udevd和udevstart就足矣,其他的工具则可以帮助我们完成udev的信息察看、事件捕捉或者更高级的操作。

2)、创建udev配置文

# cd /srv/rootfs
# mkdir -p etc/udev/rules.d
# cd etc/udev
# vim udev.conf
udev_root="/dev"
udev_rules="/etc/udev/rules.d"
udev_log="err"

# vim rules.d/udev.conf

###############################################
# vc
devices KERNEL=="tty[0-9]*", NAME="vc/%n"

# block devices
KERNEL=="loop[0-9]*", NAME="loop/%n"

# mtd devices
KERNEL=="mtd[0-9]*", NAME="mtd/%n"
KERNEL=="mtdblock*", NAME="mtdblock/%n"

# input devices
KERNEL=="mice" NAME="input/%k"
KERNEL=="mouse[0-9]*", NAME="input/%k"
KERNEL=="ts[0-9]*", NAME="input/%k"
KERNEL=="event[0-9]*", NAME="input/%k"

# misc devices
KERNEL=="apm_bios", NAME="misc/%k"
KERNEL=="rtc",NAME="misc/%k"
################################################

到此,我们的设备文件系统基本上就可以了,udevd和udevstart会自动分析这个配置文件。
版本为2.6.22.x的内核默认支持hotplug,sysfs和tmpfs,可以通过:

make menuconfig-->General setup-->Configure standard kernel features(for small systems)(安空格选中它)-->Support hot-pluggable devices

make menuconfig-->File systems-->Pseudo filesystems-->选中/proc, /proc/sys, sysfs和Virtual memory file system support(包含tmpfs)

 

4.4、增加需要的共享库:
# cd /usr/local/arm/BUILD/rootfs/lib
# cp -rp /usr/local/arm/4.2.1/lib/*  ./
arm-linux-strip *
# cp -rp /usr/local/arm/BUILD/rootfs/*  /srv/rootfs
上面的方法只是简单地把开发工具链中的共享库全部拷贝到嵌入式根文件系统中,但是这样拷贝会把很多用不上的库拷贝过去,最好的方式是通过查询每一个程序所依赖的共享库,然后一个一个拷贝过去。查询程序的依赖共享库的命令是arm-linux-readelf -d <program> | grep "Shared library“

 

5、打包成各种类型的根文件系统

5.1、NFS根:

前提是开发板和电脑通过网线相连,并且网络是通的(至于如何配置u-boot下载模式下与电脑联网请从网上搜索)。在电脑端执行:
# apt-get  install  nfs-kernel-server
# vim /etc/exports
/srv/rootfs        *(rw,no_root_squash)
/etc/init.d/nfs-kernel-server restart

启动开发板并进入u-boot的下载模式,执行如下命令:
$ setenv bootargs console=ttyS0,115200 mem=64m rw root=/dev/nfs nfsroot=200.200.200.2:/srv/rootfs init=/sbin/init ip=200.200.200.3:200.200.200.2:200.200.200.2:255.255.255.248:MyTarget:eth0:off
$ saveenv

然后启动内核,显示信息类似下面:

……

Creating 5 MTD partitions on "flash0":
0x00000000-0x00040000 : "boot"
0x00040000-0x00080000 : "param"
0x00080000-0x00380000 : "Kernel"
0x00380000-0x01280000 : "rootfs"
0x01280000-0x02000000 : "appfs"
mice: PS/2 mouse device common for all mice
TCP cubic registered
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
XScale iWMMXt coprocessor detected.
eth0: link down
IP-Config: Complete:
device=eth0, addr=200.200.200.3, mask=255.255.255.248, gw=200.200.200.2,
host=MyTarget, domain=, nis-domain=(none),
bootserver=200.200.200.2, rootserver=200.200.200.2, rootpath=
Looking up port of RPC 100003/2 on 200.200.200.2
eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
Looking up port of RPC 100005/1 on 200.200.200.2
VFS: Mounted root (nfs filesystem).
Freeing init memory: 96K
Bad inittab entry at line 1

Please press Enter to activate this console.


5.2、创建RAMDISK根:

RAMDISK只是一个ext2文件系统,创建ext2文件系统的工具随系统携带,创建一个基于ramdisk的根的步骤如下(假定tftpd的工作目录是/srv/tftp):
apt-get install tftpd tftp openbsd-inetd
# vim /etc/inetd.conf
tftp            dgram   udp     wait    nobody  /usr/sbin/tcpd  /usr/sbin/in.tftpd /srv/tftp
# cd /usr/local/arm/BUILD
# dd if=/dev/zero of=rootfs-ramdisk.bin bs=1k count=16384
# mke2fs –F –m0 rootfs-ramdisk.bin
# mount –t ext2 rootfs-ramdisk.bin /mnt –o loop
# tar –C rootfs –cf - . | tar –C /mnt –xf –
# umount /mnt
# cp rootfs-ramdisk.bin /srv/tftp

为了使内核能找到ramdisk的根,u-boot的环境变量bootargs必须修改,bootargs定义了一些传递给内核的参数,如内存大小、ip地址、根在何处以及根的类型等等,我们的bootargs如下:

$ setenv bootargs mem=64M ip=dhcp console=ttyS0,115200n8                     root=/dev/ram0 rw initrd=0x81600000,16M ramdisk_size=16384
$ saveenv

好了,现在下载内核和根:
$ tftp 81600000 rootfs-ramdisk.bin
$ tftp 80000000 uImage
$ bootm

然后应该看到类似如下的启动信息:

RAMDISK: ext2 filesystem found at block 0
RAMDISK: Loading 16384KiB [1 disk] into ram disk... done.
VFS: Mounted root (ext2 filesystem).
Freeing init memory: 136K
init started: BusyBox v1.11.1 (2008-10-05 04:40:51 CDT)
starting pid 287, tty : '/etc/init.d/rcS'

   System initialization...

   Hostname       : OMAP3EVM
   Filesystem     : v1.0.0

   Kernel release : Linux 2.6.22.18-omap3
   Kernel version : #12 Mon Oct 6 01:22:49 CDT 2008

Mounting /proc             : [SUCCESS]
Mounting /sys              : [SUCCESS]
Mounting /dev              : [SUCCESS]
Mounting /dev/pts          : [SUCCESS]
Enabling hot-plug          : [SUCCESS]
Populating /dev            : [SUCCESS]
Disabling Power mgmt       : [SUCCESS]
Turn off LCD after 1 hour  : [SUCCESS]
Mounting other filesystems : [SUCCESS]
Starting syslogd           : [SUCCESS]
Starting telnetd           : [SUCCESS]

System initialization complete.

Please press Enter to activate this console.

5.3、MTD分区:

在讨论基于flash的文件系统前,我们必须先搞清楚MTD分区的概念。嵌入式设备上的flash必须分区,这一点就像硬盘,比如在PC机上安装Linux时,可以分为/boot,交换区和根分区等等。而对于嵌入式设备,flash一把分为bootloader分区,bootloader参数分区,内核分区和数据文件系统分区等。但是不像硬盘分区信息那样保存在硬盘上,flash分区是在软件代码里指定的,当然具体的分区还与flash芯片、核心板、CPU和Linux源代码有关。比如我们的开发板Xscale270的内核分区文件为drivers/mtd/maps/xsbase270-flash.c:

……

static struct mtd_partition xsbase270flash_partitions[] = {
{
.name =         "bootloader",
.size =         0x00040000,
.offset =       0,
.mask_flags =   MTD_WRITEABLE  /* force read-only */
},{
.name =         "param",
.size =         0x00040000,
.offset =       0x00040000,
},{
.name =         "Kernel",
.size =         0x00300000,
.offset =       0x00080000,
},{
.name =         "rootfs",
.size =         0x00f00000,
.offset =       0x00380000,
},{
.name =         "appfs",
.size =         MTDPART_SIZ_FULL,
.offset =       0x01280000,

}
};

……

从上面的代码中我们可以知道,flash只分了五个区,分别用来存放bootloader(256KB)、bootloader参数(256k)、内核(3MB)、根文件系统(15MB)和应用文件系统(13MB)。

这样内核在启动时,会自动装入相应的flash驱动,为每个分区创建设备节点文件,设备文件的格式是/dev/mtdblock/x或者/dev/mtdblockx:

Flash
Physical Adress Range  Bank  Device Node     Partition Name
0x00000000-0x0003ffff  1     /dev/mtdblock0  "bootloader"
0x00040000-0x0007ffff  1     /dev/mtdblock1  "param"
0x00080000-0x0037ffff  1     /dev/mtdblock2  "Kernel"
0x00380000-0x0127ffff  1     /dev/mtdblock3  "rootfs"
0x01280000-0x01ffffff  1     /dev/mtdblock4  "appfs"

5.4、创建JFFS2类型的根并烧写到flash中:

apt-get install mtd-utils
mkfs.jffs2 -lqnp -o /srv/tftp/rootfs270.img -e 0x40000 -r /srv/rootfs

在u-boot的命令行:

tftp 0xa0008000 rootfs270.img
protect off all
era 0x380000 +0xf00000
cp.b  0xa0008000 0x380000 0xf00000
setenv bootargs mem=64M noinitrd ip=200.200.200.3:200.200.200.2:200.200.200.2:255.255.255.248:MyTarget:eth0:off console=ttyS0,115200n8 root=/dev/mtdblock3 rootfstype=jffs2
saveenv
protect on all

 

 

losetup -f ----寻找一个空loop设备,比如是loop1
losetup /dev/loop1 /tmp/rootfs.jffs2

modprobe block2mtd
echo "/dev/loop0" > /sys/module/block2mtd/parameters/block2mtd
modprobe mtdblock
ls /dev/mtdblock0 ----应该有

mount -t jffs2 -o ro /dev/mtdblock0 /mnt/jffs2
tar -cf - -C /mnt/jffs2 . | tar xvf - -C /tmp/rootfs

 

未完待续……
本文参考了文章:
http://processors.wiki.ti.com/index.php/Creating_a_Root_File_System_for_Linux_on_OMAP35x


 

 

分页阅读:上一页 1
目前有2条回应
Comment
Trackback
Loading ....
  • 重庆交通违章查询 回应于2011/08/27 19:50 回复TA

    严重支持楼主!申请个友情链接:http://www.2ge8.com

  • traducere italiana 回应于2012/10/04 21:44 回复TA

    When I first saw this title 制作嵌入式根文件系统 | 非常开源–开源盛世的博客 on google I just whent and bookmark it.Hi, I do believe this is an excellent site. I stumbledupon it I'm going to come back yet again since I book-marked it. Money and freedom is the greatest way to change, may you be rich and continue to help other people.

  • 本篇文章没有Trackback
你目前的身份是游客,请输入昵称和电邮!

Verify Code   If you cannot see the CheckCode image,please refresh the page again!