嵌入式Linux根文件系统制作

本文详细介绍了嵌入式Linux根文件系统,包括根文件系统的概念、作用和重要性,以及如何制作根文件系统。文章还讨论了不同类型的文件系统,如initramfs、jffs2、yaffs2、ubifs等,并提供了mtd-utils工具的源码编译过程。最后,文中展示了如何调整内核Nandflash分区表以及挂载和管理UBIFS文件系统。
摘要由CSDN通过智能技术生成
嵌入式Linux根文件系统制作

一、根文件系统简介
    根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统而言它还是内核启动时所挂载(mount)的第一个文件系统,系统引导启动程序会在根文件系统挂之后从中把一些初始化脚本(如inittab、rcS)和服务加载到内存中去运行。我们要明白文件系统和内核是完全独立的两个部分。在嵌入式中移植的内核下载到开发板上,是没有办法真正的启动Linux操作系统的,会出现无法加载文件系统的错误。
    根文件系统之所以在前面加一个”根“,说明它是加载其它文件系统的”根“,既然是根的话,那么如果没有这个根,其它的文件系统也就没有办法进行加载的。它包括了Linux启动时所必须的目录和关键性的文件,例如Linux启动时都需要有init目录下的相关文件,在 Linux挂载分区时Linux一定会找/etc/fstab这个挂载配置文件等,根文件系统中还包括了应用程序(如ls、mkdir、rm、ifconfig等命令)和 GNU C 库(glibc、eglibc或uclibc)等。任何包括这些Linux 系统启动所必须的文件都可以成为根文件系统。Linux启动时,第一个必须挂载的是根文件系统;若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。成功之后可以自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。
    在 Linux 中将一个文件系统与一个存储设备关联起来的过程称为挂载(mount)。使用 mount 命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂载时,要提供文件系统类型、文件系统和一个挂载点。根文件系统被挂载到根目录下“/”上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt等,再将其他分区挂接到/mnt目录上,/mnt目录下就有这个分区的各个目录,文件。Linux操作系统可以支持多种多样不同的文件系统,如windows下的FAT32、NTFS,Linux服务器使用的ext2、ext3、ext4、btrfs、xfs、reiser4、ufs、hfs(苹果系统),Linux操作系统自身使用的伪文件系统如swap、proc、sysfs、tmpfs等,也有一些设备的文件系统如iso9660(光盘)、nfs(网络文件系统)等,当然还包括我们嵌入式设备上用的不同的文件系统如:initramfs(在内存中运行的文件系统)、jffs2(一种基于Norflash的文件系统,也支持小页的nandflash)、ubifs(目前Android手机上的Nandflash普遍使用的文件系统)、yaffs2(早期专门用来支持大页Nandflash的文件系统,具备可移植性可在单片机裸机情况下使用)、cramfs(一种基于内存的只读的文件系统)、squashfs(在openwrt路由器上广泛使用的俄文件系统)、romfs(一种只读、支持片上执行XIP的文件系统,在uClinux中广泛使用)等。下面是几种常用的嵌入式根文件系统的对比:
          initramfs 该文件系统直接将根文件系统直接打包进Linux内核里(只有这种文件系统具有该功能),这样内核和根文件系统绑定在一块成为一个单独的文件,他在Linux系统启动后加载到内存中运行,所以速度快,但浪费内存,系统升级的时候内核和根文件系统一起升级比较方便。但因为他是基于内存的文件系统,所以系统掉电后针对根文件系统下所有文件的修改掉电都会丢失,如果要升级根文件系统只有重新编译、烧录Linux内核;
          jffs2 专门针对Norflash设计的文件系统,小页的Nandflash也可以使用,只是效率不高;因为根文件系统存放在Flash上,所以根文件系统路径下的文件修改后掉电仍然存在;
          yaffs2 早期专门针对大页Nandflash设计的文件系统,他的源码独立于Linux内核维护着,所以可以在单片机等裸机环境下使用(只有该文件系统可以),linux内核想用它必须要打上补丁;在分区较大时,nandflash的挂载时间较长,现在逐渐被ubifs广泛替代;
          ubifs 专门针对Nandflash设计的一种文件系统,他在内核的MTD一层上面又建立了UBI一层,挂载速度、磨损均衡、读写速度非常快,目前nandflash上应用得最广的一种根文件系统;
  
  Linux操作系统之所以能够支持这么多种不同的文件系统,主要是通过叫做VFS的中间层对这些文件系统提供了完美的支持。对于用户来说,这些文件系统几乎是透明的,在大部分情况下,用户通过libc和kernel的VFS交互,不需要关心底层文件系统的具体实现,但是有时应用程序也需要考虑底层文件系统限制(比如fat vfat不支持链接,比如各个文件系统支持最大文件限制不同)。VFS主要有以下特性:
        1. 向上,对应用层提供一个标准的文件操作接口,如open()、read()、write()、ioct()、close()等;
        2. 对下,对所有文件系统提供一个统一的标准接口,以便其他操作系统的文件系统可以方便的移植到Linux上;
        3. VFS内部则通过一系列高效的管理机制,比如inode cache, dentry cache 以及文件系统的预读等技术,使得底层文件系统不需沉溺到复杂的内核操作,即可获得高性能;
        4. 此外VFS把一些复杂的操作尽量抽象到VFS内部,使得底层文件系统实现更简单。
下图是Linux内核里文件系统的分层结构图:
二、mtd-utils工具源码编译
    Linux内核MTD对同一Flash分区提供了两种设备文件给用户层使用,一种是/dev/mtdblockX块设备,该设备用来建立文件系统并挂载起来使用;另外一种相对应的/dev/mtdX字符设备,其里面添加了
一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。而mtd-util就是以这些ioctl为基础而实现的工具,实现一些关于Flash的操作,如flash_erase、flash_eraseall、flashcp、nandwrite等命令,此外在PC上制作根文件系统所需要的一些工具也在里面,如制作JFFS2根文件系统用的mkfs.jffs2、制作UBIFS根文件系统工具mkfs.ubifs以及开发板上操作UBI文件系统的命令。
    这里我们只介绍PC端的源码编译来获取mkfs.jffs2和mkfs.ubifs工具,如果相应的工具需要放在ARM开发板上运行则需要使用交叉编译器编译。mtd_utils需要lzo、zlib和e2fsprogs这三个库,所以在编译mtd_utils之前先需要编译这三个库。Linux下使用源码安装工具时,如果有Makefile则直接用make命令编译,如果没有Makefile文件,则一般有个configure的脚本,该源码结构的编译三步曲:
./configure、make、make install

2.1 创建mtd-utils的工作路径
[wudongxu@centos6_master ~]$ cd gitee/fl2440/
[wudongxu @centos6_master fl2440]$ mkdir -p x86_tools/mtd_utils
    mtd-utils编译依赖lzo、zlib和libuuu这几个库,所以我们在编译它之前先要编译这些库。另外,为了在运行mkfs.jffs2和mkfs.ubifs这些命令时不依赖这些动态库,我们采用静态编译、然后静态链接生成这两个命令。

2.2 编译lzo库
[wudongxu @centos6_master ~]$ cd ~/gitee/fl2440/x86_tools/mtd_utils/
[wudongxu @centos6_master mtd_utils]$ wget  http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz 下载lzo库
[wudongxu @centos6_master mtd_utils]$ tar -xzf lzo-2.10.tar.gz
[wudongxu @centos6_master mtd_utils]$ cd lzo-2.10
[wudongxu @centos6_master lzo-2.10]$ ./configure --help 查看configure帮助信息,可以看出他支持哪些参数
[wudongxu @centos6_master lzo-2.10]$ ./configure --prefix=`pwd`/../install --enable- static --disable-shared --prefix 指定安装路径 --enable-static指定生产静态库 --disable- shared 指定不要生成动态库
[wudongxu @centos6_master lzo-2.10]$ make && make install

2.3 编译zlib库
[wudongxu @centos6_master ~]$ cd ~/gitee/fl2440/x86_tools/mtd_utils/
[wudongxu @centos6_master mtd_utils]$ wget  https://github.com/madler/zlib/archive/v1.2.10.tar.gz -O zlib-1.2.10.tar.gz
[wudongxu @centos6_master mtd_utils]$ tar -xzf zlib-1.2.10.tar.gz
[wudongxu @centos6_master mtd_utils]$ cd zlib-1.2.10
[wudongxu @centos6_master zlib-1.2.10]$ ./configure --prefix=`pwd`/../install --static
[wudongxu @centos6_master zlib-1.2.10]$ make && make install

2.4 编译e2fsprogs库(libuuid)
[wudongxu @centos6_master ~]$ cd ~/gitee/fl2440/x86_tools/mtd_utils/
[wudongxu @centos6_master mtd_utils]$ wget  https://github.com/tytso/e2fsprogs/archive/v1.43.7.tar.gz -O e2fsprogs-1.43.7.tar.gz
[wudongxu @centos6_master mtd_utils]$ tar -xzf e2fsprogs-1.43.7.tar.gz
[wudongxu @centos6_master mtd_utils]$ cd e2fsprogs-1.43.7/
[wudongxu @centos6_master e2fsprogs-1.43.7]$ ./configure --prefix=`pwd`/../install -- enable-elf-shlibs --enable-libuuid
[wudongxu @centos6_master e2fsprogs-1.43.7]$ make ; make install-libs

2.5 编译mtd-utils并安装mkfs.jffs2和mkfs.ubifs
[wudongxu @centos6_master ~]$ cd ~/gitee/fl2440/x86_tools/mtd_utils/
[wudongxu @centos6_master mtd_utils]$ wget ftp://ftp.infradead.org/pub/mtd- utils/mtd-utils-1.5.2.tar.bz2
[wudongxu @centos6_master mtd_utils]$ tar -xjf mtd-utils-1.5.2.tar.bz2
[wudongxu @centos6_master mtd_utils]$
[wudongxu @centos6_master mtd-utils-1.5.2]$ export CFLAGS+=" -I../install/include/ "
[wudongxu @centos6_master mtd-utils-1.5.2]$ export CFLAGS+=" -I../install/include/ "
[wudongxu @centos6_master mtd-utils-1.5.2]$ export LDFLAGS+=" -L../install/lib/ - static "
[wudongxu @centos6_master mtd-utils-1.5.2]$ make WITHOUT_XATTR=1

安装接下来制作根文件系统所需的两个工具到系统中:
[wudongxu @centos6_master mtd-utils-1.5.2]$ sudo cp mkfs.jffs2 /bin/
[wudongxu @centos6_master mtd-utils-1.5.2]$ sudo cp mkfs.ubifs/mkfs.ubifs /bin/
[wudongxu @centos6_master mtd-utils-1.5.2]$ sudo cp ubi-utils/ubinize /bin/

三、内核调整Nandflash分区表
FL2440上使用K9F2G08这个256MB的Nandflash,就像PC上的硬盘一样,我们也需要对整个Nandflash进行分区。只不过这个分区的过程是通过在Linux的源码修改来调整,接下来我们按照下面这个分区表来调整Linux系统的分区表。
[wudongxu @centos6_master ~]$ cd gitee/fl2440/linux/linux-3.0
[wudongxu @centos6_master linux-3.0]$ vim arch/arm/plat-s3c24xx/common-smdk.c
/* NAND pa
rititon from 2.4.18-swl5 */
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "mtdblock0 u-boot 1MB",
.offset = 0,
.size = SZ_1M*1, /* 0x0000000 ~ 0x0100000 */
},[1] = {
.name = "mtdblock1 kernel 15MB",
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_1M*15, /* 0x0100000 ~ 0X1000000 */
},[2] = {
.name = "mtdblock2 rootfs 40MB",
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_1M*40, },[3] = {
.name = "mtdblock3 apps 80MB",
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_1M*80, },[4] = {
.name = "mtdblock4 data 80MB",
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_1M*80, },[5] = {
.name = "mtdblock5 backup 40MB",
.offset = MTDPART_OFS_NXTBLK,
.size = SZ_1M*40, }
};
static struct s3c2410_nand_set smdk_nand_sets[] = {
重新编译Linux内核并启动,这时我们就会发现内核启动时打印出新的分区信息
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns
s3c24xx-nand s3c2440-nand: NAND soft ECC
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 94 at 0x000000bc0000
Bad eraseblock 418 at 0x000003440000
Bad eraseblock 713 at 0x000005920000
Bad eraseblock 1144 at 0x000008f00000
Bad eraseblock 1940 at 0x00000f280000
Bad eraseblock 2010 at 0x00000fb40000
Creating 6 MTD partitions on "NAND":
0x000000000000-0x000000100000 : "mtdblock0 u-boot 1MB" 0x000000100000-0x000001000000 : "mtdblock1 kernel 15MB" 0x000001000000-0x000003800000 : "mtdblock2 rootfs 40MB" 0x000003800000-0x000008800000 : "mtdblock3 apps 80MB" 0x000008800000-0x00000d800000 : "mtdblock4 data 80MB" 0x00000d800000-0x000010000000 : "mtdblock5 backup 40MB" dm9000 Ethernet Driver, V1.31
eth0: dm9000a at c4862300,c4864304 IRQ 51 MAC: 08:00:3e:26:0a:5b (chip)
登录开发板Linux后,我们也可以使用 cat /proc/mtd 命令查看分区信息
~ >: cat /proc/mtd
dev: size erasesize name
mtd0: 00100000 00020000 "mtdblock0 u-boot 1MB"
mtd1: 00f00000 00020000 "mtdblock1 kernel 15MB"
mtd2: 02800000 00020000 "mtdblock2 rootfs 40MB"
mtd3: 05000000 00020000 "mtdblock3 apps 80MB"
mtd4: 05000000 00020000 "mtdblock4 data 80MB"
mtd5: 02800000 00020000 "mtdblock5 backup 40MB" 开发板Linux系统的路径下会产生相应的分区文件,其中mtdX(X为0,1,2,3....)为可读写字符设备, mtdXro为只读的字符设备, mtdblockX为mount命令挂载使用的块设备。
~ >: ls -l /dev/mtd* crw-rw---- 1 root root 90, 0 Jan 1 00:00 /dev/mtd0
crw-rw---- 1 root root 90, 1 Jan 1 00:00 /dev/mtd0ro
crw-rw---- 1 root root 90, 2 Jan 1 00:00 /dev/mtd1
crw-rw---- 1 root root 90, 3 Jan 1 00:00 /dev/mtd1ro
crw-rw---- 1 root root 90, 4 Jan 1 00:00 /dev/mtd2
crw-rw---- 1 root root 90, 5 Jan 1 00:00 /dev/mtd2ro
crw-rw---- 1 root root 90, 6 Jan 1 00:00 /dev/mtd3
crw-rw---- 1 root root 90, 7 Jan 1 00:00 /dev/mtd3ro
crw-rw---- 1 root root 90, 8 Jan 1 00:00 /dev/mtd4
crw-rw---- 1 root root 90, 9 Jan 1 00:00 /dev/mtd4ro
crw-rw---- 1 root root 90, 10 Jan 1 00:00 /dev/mtd5
crw-rw---- 1 root root 90, 11 Jan 1 00:00 /dev/mtd5ro
brw-rw---- 1 root root 31, 0 Jan 1 00:00 /dev/mtdblock0
brw-rw---- 1 root root 31, 1 Jan 1 00:00 /dev/mtdblock1
brw-rw---- 1 root root 31, 2 Jan 1 00:00 /dev/mtdblock2
brw-rw---- 1 root root 31, 3 Jan 1 00:00 /dev/mtdblock3
brw-rw---- 1 root root 31, 4 Jan 1 00:00 /dev/mtdblock4
brw-rw---- 1 root root 31, 5 Jan 1 00:00 /dev/mtdblock5
四、jffs2根文件系统制作
4.1 jffs2文件系统简介
JFFS2全名是 Journalling Flash File System Version2,是Redhat公司开发的Flash的文件系统,其
前身是JFFS, 最早只支援Norflash, 自2.6版以后开始支援NAND Flash,其功能就是管理在MTD设备
上实现的日志型文件系统,极适合使用于嵌入式系统。与其他的存储设备存储方案相比,JFFS2并不准
备提供让传统文件系统也可以使用此类设备的转换层。它只会直接在MTD设备上实现日志结构的文件系
统。JFFS2会在安装的时候,扫描MTD设备的日志内容,并在RAM中重新建立文件系统结构本身。除了
提供具有断电可靠性的日志结构文件系统,JFFS2还会在它管理的MTD设备上实现“损耗平衡”和“数
据压缩”等特性。下面是JFFS2的不足之处:
JFFS2 的挂载(mount)过程需要对Flash从头到尾的扫描,这个过程是很慢的,我们在测试中发
现,挂载一个 16M 的闪存有时需要半分钟以上的时间
JFFS2 在分区的空间使用率比较大后,数据的读写非常缓慢
JFFS2 对磨损平衡是用概率的方法来解决的,这很难保证磨损平衡的确定性。在某些情况下,可
能造成对擦写块不必要的擦写操作;在某些情况下,又会引起对磨损平衡调整的不及时。
JFFS2没有write-back机制,不能将资料暂存于缓存(cache), 以致于flash I/O的动作频繁。
JFFS2是针对早起的Norflash和小页(页大小<4K)的Nandflash设计的,并不适合大页的Nandflash。
所以我们一般在Norflash上使用JFFS2文件系统,而现在普遍使用的大页Nandflash并不适用它。
4.2 根文件系统镜像文件制作
我们可以使用mtd-utils源码编译出来的mkfs.jffs2工具,将根文件系统树目录制作成jffs2根文件系统
镜像。在开始制作镜像之前,我们先看看mkfs.jffs2的使用说明:
[wudongxu @centos6_master linux]$ mkfs.jffs2 -h
mkfs.jffs2: error!: Usage: mkfs.jffs2 [OPTIONS]
Make a JFFS2 file system image from an existing directory tree
Options:
-p, --pad[=SIZE] Pad output to SIZE bytes with 0xFF. If SIZE is 指
定jffs2文件系统镜像的填充大小
not specified, the output is padded to the end of
the final erase block
-r, -d, --root=DIR Build file system from directory DIR (default: cwd) 指
定根文件系统目录树的路径 -s, --pagesize=SIZE Use page size (max data node size) SIZE. 指
定Nandflash的页大小
Set according to target system's memory management
page size (default: 4KiB)
-e, --eraseblock=SIZE Use erase block size SIZE (default: 64KiB) 指
定Nandflash的块大小 -c, --cleanmarker=SIZE Size of cleanmarker (default 12)
-m, --compr-mode=MODE Select compression mode (default: priority)
-x, --disable-compressor=COMPRESSOR_NAME
Disable a compressor
-X, --enable-compressor=COMPRESSOR_NAME
Enable a compressor
-y, --compressor-priority=PRIORITY:COMPRESSOR_NAME
Set the priority of a compressor
-L, --list-compressors Show the list of the available compressors
-t, --test-compression Call decompress and compare with the original (for
test)
-n, --no-cleanmarkers Don't add a cleanmarker to every eraseblock 指
定不添加清除标记
-o, --output=FILE Output to FILE (default: stdout)
指定制作出来的根文件系统镜像文件名 -l, --little-endian Create a little-endian filesystem
-b, --big-endian Create a big-endian filesystem
-D, --devtable=FILE Use the named FILE as a device table file
-f, --faketime Change all file times to '0' for regression testing
-q, --squash Squash permissions and owners making all files be owned
by root
-U, --squash-uids Squash owners making all files be owned by root
-P, --squash-perms Squash permissions on all files
--with-xattr stuff all xattr entries into image
--with-selinux stuff o
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值