其他分享
首页 > 其他分享> > jffs2根文件系统制作

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的使用说明:

我们可以使用mtd-utils源码编译出来的mkfs.jffs2工具,将根文件系统树目录制作成jffs2根文件系统
镜像。在开始制作镜像之前,我们先看看mkfs.jffs2的使用说明:
zhanghang@ubuntu:~/fl2440/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
                          not specified, the output is padded to the end of
                          the final erase block//指定jffs2文件系统镜像的填充大小
  -r, -d, --root=DIR      Build file system from directory DIR (default: cwd)//指定根文件系统目录树的路径
  -s, --pagesize=SIZE     Use page size (max data node size) SIZE.
                          Set according to target system's memory management
                          page size (default: 4KiB)//指定Nandflash的页大小
  -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: priortiry)
  -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 avaiable 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 only SELinux Labels into jffs2 image
      --with-posix-acl    stuff only POSIX ACL entries into jffs2 image
  -h, --help              Display this help text
  -v, --verbose           Verbose operation
  -V, --version           Display version information
  -i, --incremental=FILE  Parse FILE and generate appendage output for it

先看看之前做好的根文件系统大小:

zhanghang@ubuntu:~/fl2440/linux$ du -sh rootfs
12M     rootfs
zhanghang@ubuntu:~/fl2440/linux$ mkfs.jffs2 -n -s 2048 -e 128KiB -d ./rootfs -o rootfs-jffs2.bin  // 制作根文件系统时不进行填充
zhanghang@ubuntu:~/fl2440/linux$ mkfs.jffs2 -n -s 2048 -e 128KiB -d ./rootfs -o rootfs-jffs2.bin --pad=0xa00000 //// 制作根文件系统时进行填充

具体作用如下:

-n 指明不添加清除标记(nand flash 有自己的校检块,存放相关的信息),如果挂载后会出现
下面类似警告信息,则加上-n 就会消失:
s 指定Nandflash的页大小为2KB
-e 指定Nandflash的擦除块大小为128KB
-d 指定根文件系统目录树的路径 为./rootfs
-o 指定制作生成的根文件系统镜像文件名为 rootfs-jffs.bin,该文件需要u-boot烧录到
Nandflash的相应分区
–pad=0xa00000 将制作的根文件系统镜像(rootfs-jffs2.bin)文件大小用0xFF填充为–pad指
定的值。如果在制作根文件系统的不填充的话,Linux挂载启动根文件系统时将会出现下面警告
信息。

我们在之前的Linux内核Nandflash分区修改里将rootfs分区大小设置为40M,所以这里的–pad值
应该为0x280000。但如果使用0x2800000,则根文件系统镜像的大小就为40M,这样u-boot下载烧
录的时间较长,另外如果在Nandflash上烧录该镜像文件的分区存在坏块的话,则在u-boot里用nand
write烧录时会跳过坏块溢出到下一个分区空间中去,从而占用了下一个空间的使用,系统就会出错。这
里我们将填充大小值设置为10M是也可以解决上面jffs2_scan_eraseblock抛出的警告信息,之所以将
填充大小设置为10M是因为不进行填充时制作的根文件系统镜像大小为6.3M,这个值的大小根据分区
大小和根文件系统目录树的实际大小进行调整。

4.3 内核配置和编译

zhanghang@ubuntu:~/fl2440/linux$ cd linux-3.0/
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ export TERM=vt100
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ make menuconfig
General setup --->
		[ ] Automatically append version information to the version string 取消这个选项减少内核大小
		[ ] Support for paging of anonymous memory (swap) Nandflash不需要swap分区,如果是PC上的硬盘则需要swap分区
		<*> Kernel .config support
		[ ] Initial RAM filesystem and RAM disk (initramfs/initrd) support 一定要取消initramfs的支持,否则内核找到initramfs则直接使用initramfs启动
		[*] Configure standard kernel features (expert users) ---> 添加这个选项
		[*] Embedded system 添加这个选项
File systems --->
		< > Second extended fs support 取消PC端用的ext2文件系统支持,减少内核大小
		< > Ext3 journalling file system support 取消PC端用的ext3文件系统支持,减少内核大小
		< > The Extended 4 (ext4) filesystem 取消PC端用的ext4文件系统支持,减少内核大小
		< > Kernel automounter version 4 support (also supports v3) 取消这个选项减少内核大小
		< > FUSE (Filesystem in Userspace) support 取消这个选项减少内核大小
		CD-ROM/DVD Filesystems --->
				< > ISO 9660 CDROM file system support 取消这个光驱光盘选项,减少内核大小
				< > UDF file system support 取消这个光驱光盘选项,减少内核大小
		DOS/FAT/NT Filesystems --->
				<*> MSDOS fs support
				<*> VFAT (Windows-95) fs support 添加Windows的FAT文件系统支持,U盘或SD卡中会使用
				(437) Default codepage for FAT
				(iso8859-1) Default iocharset for FAT
				<*> NTFS file system support 添加Windows的NTFS文件系统支持,U盘或SD卡中会使用
				[ ] NTFS debugging support
				[*] NTFS write support
		Pseudo filesystems --->
				<*> Userspace-driven configuration filesystem 添加sysfs伪文件系统支持
		[*] Miscellaneous filesystems --->
				<*> Journalling Flash File System v2 (JFFS2) support 添
加JFFS2文件系统支持
				(0) JFFS2 debugging verbosity (0 = quiet, 2 = noisy)
				[*] JFFS2 write-buffering support
				[ ] Verify JFFS2 write-buffer reads
				[*] JFFS2 summary support (EXPERIMENTAL)
				[ ] JFFS2 XATTR support (EXPERIMENTAL)
				[ ] Advanced compression options for JFFS2其他文件系统如果不需要的话都不要选
				< > Compressed ROM file system support (cramfs) 如果不用的话,取消cramfs文件系统的支持
				< > SquashFS 4.0 - Squashed file system support 如果不用的话,取消SquashFS文件系统的支持
				< > ROM file system support 如果不用的话,取消ROM文件系统的支持
[*] Network File Systems --->
		<*> NFS client support
		[*] NFS client support for NFS version 3
		[*] NFS client support for the NFSv3 ACL protocol extension
		[ ] NFS client support for NFS version 4
		[*] Root file system on NFS
		将其他不需要的网络文件系统都不要选
		< > NFS server support
		< > Ceph distributed file system (EXPERIMENTAL)
		< > CIFS support (advanced network filesystem, SMBFS successor)
		< > NCP file system support (to mount NetWare volumes)
		< > Coda file system support (advanced network fs)
		< > Andrew File System support (AFS) (EXPERIMENTAL)
Partition Types --->
		[ ] PC BIOS (MSDOS partition tables) support 取消这个选项减少内核大小
-*- Native language support ---> U盘的挂载可能需要下面这些语言编码的支持,譬如简体中文的CP936和GB2312等
		(iso8859-1) Default NLS Option
		<*> Codepage 437 (United States, Canada)
		<*> Simplified Chinese charset (CP936, GB2312)
		<*> Traditional Chinese charset (Big5)
		<*> ASCII (United States)
		<*> NLS ISO 8859-1 (Latin 1; Western European Languages)
		<*> NLS UTF-8
		其他语言如果不需要全部不要选

因为禁用了initramfs重新编译Linux内核,新编译的内核不包含根文件系统所以文件较小。

  CC      sound/usb/caiaq/snd-usb-caiaq.mod.o
  LD [M]  sound/usb/caiaq/snd-usb-caiaq.ko
  CC      sound/usb/snd-usb-audio.mod.o
  LD [M]  sound/usb/snd-usb-audio.ko
  CC      sound/usb/snd-usbmidi-lib.mod.o
  LD [M]  sound/usb/snd-usbmidi-lib.ko
Image Name:   Linux Kernel
Created:      Mon Apr 29 04:56:04 2019
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    2403520 Bytes = 2347.19 kB = 2.29 MB
Load Address: 30008000
Entry Point:  30008040
zhanghang@ubuntu:~/fl2440/linux/linux-3.0$ du -h linuxrom-s3c2440.bin 
2.3M    linuxrom-s3c2440.bin

4.4 u-boot系统烧录和环境变量配置
因为使用jffs2根文件系统启动的Linux内核不包含根文件系统,所以u-boot烧录Linux系统时需要同时
烧录linux内核镜像(linuxrom-s3c2440.bin)和根文件系统镜像(rootfs-jffs2.bin),此外还要通过
bootargs环境变量告诉Linux内核根文件系统所在的位置。这里Linux内核、根文件系统的烧录地址、
bootargs传参应该与Linux内核里的Nandflash分区表相一致:
在这里插入图片描述

u-boot的烧录地址应该是 0,大小不超过1M。该分区对应Linux内核分区
表的/dev/mtdblock0;
Linux内核的烧录地址应该是0x100000(1M的偏移量处),大小不超过15M。该分区对应Linux
内核分区表的/dev/mtdblock1;
根文件系统镜像的烧录地址应该是0x1000000(16M的偏移量处),大小不超过40M。该分区对
应Linux内核分区表的/dev/mtdblock2;

烧录Linux内核命令

[fl2440@lingyun]# tftp 30008000 linuxrom-s3c2440.bin 先将Linux内核下载到内存地址30008000上去
[fl2440@lingyun]# nand erase 100000 F00000 将Nandflash上Linux内核分区(即1M开始总共15M的空间)全部擦除
[fl2440@lingyun]# nand write 30008000 100000 400000 将Linux内核写入到Nandflash上的Linux内核分区上去

烧录根文件系统命令

[fl2440@lingyun]# tftp 30008000 rootfs-jffs2.bin 先将根文件系统下载到内存地址30008000上去
[fl2440@lingyun]# nand erase 1000000 2800000 将Nandflash上根文件系统分区(即16M开始总共40M的空间)全部擦除
[fl2440@lingyun]# nand write 30008000 1000000 $filesize 将根文件系统写入到Nandflash上的根文件系统分区上去

设置bootcmd和bootargs参数:
开发板上电或重启运行u-boot时,如果不按任意键u-boot将进入正常加载模式,这时他将读取环境变量bootcmd来启动引导Linux内核。Linux内核是被烧录到Nandflash的0x100000位置上,所以uboot启动系统需要从该位置读取内核文件到内存相应位置中去,并且读取字节数应该不小于烧录的Linux镜像文件大小,否则系统将启动失败。根文件系统则通过bootargs参数告诉Linux内核,Linux内核在启动后根据该参数挂载相应的根文件系统,如果bootargs参数出错也将导致系统启动失败。

[fl2440@lingyun]# set bootcmd 'nand read 30008000 100000 400000; bootm 30008000'
[fl2440@lingyun]# set bootargs 'console=tty0 console=ttyS0,115200
root=/dev/mtdblock2 rootfstype=jffs2 init=/linuxrc mem=64M rw noinitrd loglevel=7'
[fl2440@lingyun]# save

bootargs的参数解析如下:
console=tty0 指定内核控制终端为LCD,内核启动信息输出到LCD上;
console=ttyS0,115200 指定内核控制终端也为第一个串口,使用波特率115200,这样内核启动信
息也打印到第一个串口上;
root=/dev/mtdblock2 指定根文件系统存放在mtdblock2上,该值应该与u-boot烧录位置、Linux
内核分区保持一致;如果错误则Linux内核会因找不到根文件系统而启动失败;
rootfstype=jffs2 指定根文件系统类型为jffs2,如果该参数错误则内核启动失败;
init=/linuxrc 指定init进程执行/linuxrc这个程序,他会解析并执行/etc/inittab下的命令;
mem=64M u-boot告诉Linux内核有64M的内存;
rw 根文件系统以读写的形式挂载;
noinitrd 没有使用initrd;
loglevel=7 定义内核printk的打印级别为7,即所有信息都通过console打印出来;

登录开发板,jffs2不同于initramfs,jffs2在nandflash上,掉电数据不会丢失。

...
usb 1-1: new full speed USB device number 4 using s3c2410-ohci
usb 1-1: device not accepting address 4, error -62
usb 1-1: new full speed USB device number 5 using s3c2410-ohci
usb 1-1: device not accepting address 5, error -62
hub 1-0:1.0: unable to enumerate USB device on port 1
dm9000 dm9000: eth0: link down

Default Logon Username: root Password: 123456
LingYunFL2440 login: dm9000 dm9000: eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1
root
Password: 
~ >: ls
apps     dev      init     mnt      sbin     usr
bin      etc      lib      proc     sys      var
data     info     linuxrc  root     tmp
~ >: vim aaa
nnnnnnnnnnn
aaa      data     info     linuxrc  root     tmp
apps     dev      init     mnt      sbin     usr
bin      etc      lib      proc     sys      var
~ >: reboot
...
usb 1-1: device not accepting address 4, error -62
usb 1-1: new full speed USB device number 5 using s3c2410-ohci
usb 1-1: device not accepting address 5, error -62
hub 1-0:1.0: unable to enumerate USB device on port 1
dm9000 dm9000: eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1

Default Logon Username: root Password: 123456
LingYunFL2440 login: root
Password: 
Login incorrect
LingYunFL2440 login: 
LingYunFL2440 login: root
Password: 
~ >: ls
aaa      data     info     linuxrc  root     tmp
apps     dev      init     mnt      sbin     usr
bin      etc      lib      proc     sys      var

因为JFFS2是建立在Nandflash上的根文件系统,在该文件系统路径下所有的文件修改掉电后都不会丢
失。所以我们在根路径下创建aaa文件后,把开发板重启发现该文件还存在。

~ >: mount
rootfs on / type rootfs (rw)
/dev/root on / type jffs2 (rw,relatime)
proc on /proc type proc (rw,relatime)
usbfs on /proc/bus/usb type usbfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
ramfs on /tmp type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600)

4.6 普通分区jffs2挂载
jffs2除了可以制作成根文件系统使用以外,我们也可以在系统成功启动后,将其他分区以jffs2文件系统
类型挂载使用。

~ >: dmesg | grep mtdblock //通过dmesg命令查看内核的分区情况
root=/dev/mtdblock2 rootfstype=jffs2 init=/linuxrc mem=64M rw noinitrd loglevel=7
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"
~ >: cat /proc/partitions//查看Linux内核分区表
major minor  #blocks  name

  31        0       1024 mtdblock0
  31        1      15360 mtdblock1
  31        2      40960 mtdblock2
  31        3      81920 mtdblock3
  31        4      81920 mtdblock4
  31        5      40960 mtdblock5
~ >:  ls -l /dev/mtdblock*//查看分区对应的块设备
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

这里我们以 mtdblock5 为例将其以jffs2文件系统格式挂载到 /info 挂载点上:

~ >: flash_eraseall /dev/mtd5
Erasing 128 Kibyte @ 2800000 - 100% complete.//将mtdblock5分区全部擦除
~ >: mount -t jffs2 /dev/mtdblock5 /info/
~ >: mount
rootfs on / type rootfs (rw)
/dev/root on / type jffs2 (rw,relatime)
proc on /proc type proc (rw,relatime)
usbfs on /proc/bus/usb type usbfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
ramfs on /tmp type ramfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600)
/dev/mtdblock5 on /info type jffs2 (rw,relatime)
~ >: cd info/
/info >: touch mmm
/info >: ls
mmm
/info >: cd
~ >: reboot
~ >: cd info/
/info >: ls
/info >: cd 
~ >: mount -t jffs2 /dev/mtdblock5 /info/
mount: mounting /dev/mtdblock5 on /info/ failed: Device or resource busy
~ >: ls
apps     dev      init     mnt      sbin     usr
bin      etc      lib      proc     sys      var
data     info     linuxrc  root     tmp
~ >: cd info/
/info >: ls
mmm

系统重启后,并不会自动挂载/dev/mtdblock5到/info路径下,这时我们还是需要用命令手动挂载才能
看到/info路径下的haha文件存在。
这时我们可以写一个shell脚本,使系统启动时直接挂在mtdblock5到info下

~ >:  cd etc/init.d/
/etc/init.d >: vim S_mount_block_5
#!bin/sh
mount -t jffs2 /dev/mtdblock5 /info/
/etc/init.d >: chmod a+x S_mount_block_5 

这样,每次系统启动就会将mtdblock5挂在在info下。

标签:jffs2,support,文件系统,dev,内核,root,制作
来源: https://blog.csdn.net/qq_43260665/article/details/89682567