Linux内核及文件系统移植


原文链接: Linux内核及文件系统移植

Linux内核及文件系统移植

嵌入式系统包含硬件子系统与软件子系统,其中软件子系统大致可分为:bootloader、Linux内核、文件系统与应用开发,这四个组成部分中前三者构建成嵌入式应用功能的基础运行环境,是进行嵌入式产品项目开发前期就需要敲定的配置环境,非常重要与关键。本课程主要对第三部分嵌入式文件系统的构建与移植进行介绍,讲解如何选择、配置、移植与制作一个可用的文件系统及其镜像,以及怎样配合Linux内核的配置调整来应用生成的文件系统,进而掌握构建完整的嵌入式软件子系统应用开发环境。

开发移植环境:虚拟机Ubuntu 12.04 + FriendlyARM Smart210SDK + Windows 7 Ultimate

Lesson 1. Linux内核启动参数介绍与设置

引导:
软件子系统各组成部分之间的层次与关联,怎样相互识别、配置与加载?

一、系统启动流程
bootloader(uboot) ———— Linux Kernel(uImage) ———— Rootfs(Init) ———— Applications

二、启动环境配置
uboot环境变量: printenv setenv saveenv tftpboot nand read/write ...

baudrate  115200
bootdelay
bootcmd   boot bootd运行bootcmd变量指定的命令进行启动
ipaddr, serverip, ethaddr,gatewayip
bootargs

内核启动参数:bootargs '= ...'
bootargs=root=/dev/nfs nfsroot=192.168.10.7:/home/hong/nfsroot ip=192.168.10.11 init=/linuxrc console=ttySAC0,115200

root, rootfstype, nfsroot
  root=/dev/nfs nfsroot=nfsserver:path
  root=/dev/mtdblock2
  rootfstype=jffs2/yaffs2/squashfs/ubifs/...
mtdparts: mtdparts=mtd-id:<size1>@<offset1>(<name1>),<size2>@<offset2>(<name2>)
  mtdparts=s5pv210-nand:1M(boot),5M(kernel),80M(rootfs),426M(usrfs)
  要想这个参数起作用,内核中的mtd驱动必须要支持,即内核配置时需要选上
  Device Drivers  ---> Memory Technology Device (MTD) support  ---> Command line partition table parsing
ip: nfs必须进行设置
   ip=ip addr
   ip=ip addr:server ip addr:gateway:netmask::which netcard:off
init, console
mem 限制linux内核的使用内存 mem=128M

三、启动参数设置

setenv bootargs 'root=/dev/nfs nfsroot=192.168.10.7:/home/hong/nfsroot ip=192.168.10.11 init=/linuxrc console=ttySAC0,115200'

setenv bootcmd 'tftpboot 20008000 tiny_uImage;bootm 20008000'

总结:

  1. 收集信息:flash类型与分区(nand/nor/spi.etc), 内存大小, 根文件系统类型,网络参数等(参考SDK开发手册)
  2. 配置参数:setenv bootargs '...';saveenv;
  3. 测试参数:确保内核镜像可以成功加载,必不可少的步骤
    Lession 2.Linux的根文件系统与基本框架
    ---------------------------------------
    引导:
    Q1.什么是根文件系统,为什么需要根文件系统?
    Q2.根文件系统需要满足哪些要求?

一、Linux文件系统
目录结构
树形结构:倒立 —— 根目录 /

二、根文件系统概念

  1. 是什么
    内核第一个挂载的文件系统,包含Linux系统完整启动所需的目录结构和重要文件
    其它所有文件系统进行挂载使用的载体
  2. 为什么
    Linux完整启动的需要,进入用户态操作环境:VFS设计
    提供了良好强大的文件系统扩展性

三、根文件系统形式

  1. 要求
    根文件系统能被内核找到并加载:存储介质驱动、存在地址问题
    格式能被内核识别:initrd/cramfs/...
    包含基本的目录结构与启动程序
  2. 结构
    /bin 存放二进制可执行命令的目录
    /dev 存放设备文件的目录
    /etc 存放系统管理和配置文件的目录
    /home 用户主目录,比如用户user的主目录就是/home/user,可以用~user表示
    /lib 存放动态链接共享库的目录
    /sbin 存放系统管理员使用的管理程序的目录
    /tmp 公用的临时文件存储点
    /root 系统管理员的主目录
    /mnt 系统提供这个目录是让用户临时挂载其他的文件系统。
    /proc 虚拟文件系统,可直接访问这个目录来获取系统信息。
    /var 某些大文件的溢出区
    /usr 最庞大的目录,要用到的应用程序和文件几乎都在这个目录。

    一般说来,只有/bin,/dev,/etc,/lib,/proc,/var,/usr这些需要的,而其他都是可选的。

总结:
1.概念:根文件系统必不可少,有基本的格式与结构要求
2.框架:/bin,/dev,/etc,/lib,/proc,/var,/usr

Lession 3.嵌入式根文件系统框架:busybox简介

引导:
每次从零开始构建根文件系统框架,还是可以从一个现成的通用框架开始构建满足需求的根文件系统?

一、从零开始构建最小根文件系统
/bin,/dev,/etc,/lib,/proc,/var,/usr

二、通用嵌入式根文件系统项目:busybox

  1. busybox项目: http://www.busybox.net/
    23 March 2015 -- BusyBox 1.23.2 (stable)
    嵌入式Linux的瑞士军刀
    BusyBox 将许多具有共性的小版本的UNIX工具结合到一个单一的可执行文件。这样的集合可以替代大部分常用工具比如的GNU fileutils, shellutils等工具,BusyBox提供了一个比较完善的环境,可以适用于任何小的嵌入式Linux系统。

  2. busybox源码
    下载稳定的版本
    编译构建二进制:make defconfig;make
    make menuconfig
    安装得到目录结构:make CONFIG_PREFIX=../mini_rootfs/ install

总结:
以busybox为起点,进行项目根文件系统的裁剪定制,构建自己的根文件系统。

[Lession 4]. 嵌入式根文件系统框架:启动脚本

引导:
前提:基于busybox的根文件系统移植与应用
init程序的限制性与局限性如何实现灵活动态调整的嵌入式应用启动控制?

一、init进程:linuxrc --> ELF二进制程序
/bin/busybox, 进程号1

二、/etc/inittab文件: init程序的默认配置文件
sysinit —— 为init提供初始化命令行的路径及脚本程序
respawn —— 每当相应的进程终止执行便会重新启动
askfirst —— 类似respawn,不过它的主要用途是减少系统上执行的终端应用程序的数量。它将会促使init在控制台上显示“Please press Enter to active this console”的信息,并在重新启动之前等待用户按下enter键
wait —— 告诉init必须等到相应的进程完成之后才能继续执行
once —— 仅执行相应的进程一次,而且不会等待它完成
restart —— 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身
ctrlaltdel —— 当按下Ctrl+Alt+Delete组合键时,执行相应的进程
shutdown —— 当系统关机时,执行相应的进程

三、/etc/init.d/rcS文件及/etc/init.d目录
初始化脚本:rcS --> 系统环境准备与配置
应用及服务脚本:S[0-9]* --> 应用环境准备与配置

四、编写并添加自定义的启动脚本
S71myapp_demo S01hello

总结:
1.init —— inittab —— /etc/init.d/rcS —— /etc/init.d/S[0-9][0-9]* —— Applications
2.用C编写一个应用程序,修改或者创建启动脚本使程序上电自动运行

Lession 5. 嵌入式根文件系统框架:busybox编译

怎样从源码交叉编译得到符合需求的可用busybox二进制以及根文件系统框架?

一、busybox的构建流程

  1. make menuconfig --> 裁剪定制构建选项: make defconfig
    ncurses库的支持:
    sudo apt-get install libncurses*
    aptitude search libncurses

  2. make --> 根据选项编译出二进制文件

  3. make install ---> 根据选项安装busybox

二、busybox的交叉编译

  1. 确认使用的交叉编译工具链以及其安装位置
    which arm-linux-gcc
  2. 配置busybox的编译工具链参数
    Build Options --->
    ()Cross Compiler prefix
    ()Path to sysroot

三、busybox的裁剪定制

  1. 可配置选项简介: busybox settings
    通用配置
    [ ] Don't use /usr
    构建选项:静态库、交叉编译
    [ ] Build BusyBox as a static binary (no shared libs)
    安装目录:./_install
    (./_install) BusyBox installation prefix
    注意:记得保存裁剪配置,可以查看.config文件进行简单的确认

  2. 工具应用程序定制: applets
    对应busybox的源码目录

裁剪主要目标:降低busybox的文件大小,节省存储空间
裁剪原则:确信你在做什么,否则就不要做

总结
掌握busybox的编译构建步骤和busybox的配置选项
对busybox的配置选项进行各种尝试,观察构建出的busybox体积大小在去掉哪些选项时会有显著的降低

Lession 6. 嵌入式根文件系统框架:busybox应用

使用busybox需要确保busybox的运行,以及掌握常用的工具命令。

一、补全目录与文件
补全需要的目录:

/proc /lib /etc /dev /usr /var

动态库依赖:readelf -d busybox|grep NEEDED

ld-linux.so.3  libc.so.6  libm.so.6
ld-linux.so ----> 实现动态库的链接
C库的选择:glibc,还是uclibc ----> 取决于你的交叉编译器
  glibc ---> 更全面完善的功能
  uclibc ---> 更小的体积
库文件的查找:交叉编译器的安装目录 find命令

设备文件:

/dev/console
/dev/tty1 /dev/tty2 /dev/tty3

配置文件:

拷贝 examples/bootfloppy/etc

二、机制与使用
busybox是一个二进制程序,集合大量简单常用的工具程序到单个执行文件

代码共用,让busybox更小
单一执行文件,让busybox更简单

直接使用busybox:(二进制程序)

得到可用的工具命令(applets)列表

将命令名称作为参数调用busybox:等同于直接使用命令

/bin/busybox ls ---> ls
手动创建链接文件:ln -s /bin/busybox /bin/ls
安装过程自动创建所有的链接文件 ---> make install

所有工具命令的通用选项:--help

提供命令的简洁使用说明

三、嵌入式常用的工具命令
设备驱动管理:

fdisk fsck  hwclock   mkdosfs
insmod  rmmod lsmod   mknod     modprobe
lsusb mdev  mount   umount

文本编辑处理:

mkdir mkfifo  ln    mv    cp    touch rm  unlink
awk   cat   cut   find  vi    sed   wc  tar
grep  head  tail  less  more  xargs od  stat

网络信息配置:

udhcpc  udhcpd  route netstat ping  ifconfig

系统信息管理:

chmod clear date  dd    df    echo  free
ipcrm   ipcs  ls    ps    pwd   top   uptime
kill  killall reboot  sleep sysctl  usleep

总结:
编译完成后的安装步骤是进行busybox根文件系统应用高效开始的第一步
熟悉并掌握常用的工具命令是进行busybox根文件系统应用开发的第二步
确保busybox的正确运行需要额外的库支持,这是进行busybox应用的前提条件

Lession 7 文件系统移植实践一:基于busybox制作可用根文件系统

一个开发中实用的根文件系统,还需要完善哪些内容,怎样来部署一个根文件系统?

一、完善根文件系统

  1. check程序运行库:/lib/
    从交叉编译工具目录拷贝
    libpthread.so libthread_db.so
    libresolv.so
    librt.so

  2. check配置文件: /etc目录
    /etc/inittab
    /etc/fstab: 文件内容与格式介绍, man fstab


    设备名称(分区) 挂载点 文件系统类型 挂载选项 备份检查[0|1] fsck优先级[0|1|2]
    defaults 使用默认设置,等于rw,suid,dev,exec,auto,nouser,async
    内核文件系统挂载:proc
    /etc/profile:环境变量的设置与导出
    #!/bin/sh
    PATH=/bin:/sbin:/usr/bin:/usr/sbin
    export LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
    export PATH LD_LIBRARY_PATH
    /etc/resolv.conf
    DNS配置: nameserver 192.168.10.1
  3. check启动脚本:/etc目录
    /etc/init.d/rcS
    for script in /etc/init.d/S[0-9][0-9]*
    do
    if [ -x $script ];then

    /bin/sh -c $script
    

    fi
    done
    /etc/init.d/S80network:网络配置
    ifconfig eth0 hw ether 00:aa:11:cc:01:10
    静态配置:
    ifconfig eth0 192.168.10.111 broadcast 255.255.255.0
    route add default gw 192.168.10.1
    动态配置:
    udhcpc -i eth0 -t 20 -naq

二、 制作文件系统镜像
二进制镜像是根文件系统的目录结构以某种数据组织格式打包成的二进制文件

组织格式:文件系统格式
   cramfs jffs2 yaffs2 ...

产品的生产部署阶段使用:批量烧录到产品

镜像可以方便地进行存储、分发与部署

总结:
实践取决于应用需求,原理是相通的,但是不同的需求决定需要包含哪些内容。
Lession 9 Linux内核文件系统:proc、tmpfs、devfs、sysfs


在类Unix系统中一切都是文件,那么Linux是如何将系统的运行信息、设备信息等抽象成文件进行管理的?

Linux内核实现了一套特殊的内存虚拟文件系统用于使用与文件接口统一的操作来完成系统信息管理,它们包括:
procfs、devfs、sysfs。

一、procfs
procfs是Linux内核信息的抽象文件接口,大量内核中的信息以及可调参数都被作为常规文件映射到
一个目录树中/proc.这样我们就可以简单直接的通过echo或cat这样的文件操作命令对系统信息进行查取
和调整了。大量的系统工具也通过procfs获取内核参数,例如ps、lspci等。

  1. procfs的挂载:首先确定你的内核已经支持procfs,默认支持

    mount -t proc none /proc

    使用/etc/fstab条目:none /proc proc defaults 0 0

  2. procfs的内容:
    进程信息
    系统信息

  3. procfs信息查看
    cat命令: cat /proc/cmdline

  4. procfs参数调整
    echo命令

二、tmpfs
tmpfs是一种虚拟内存文件系统,使用内存作为存储分区进行文件的临时性存取,掉电会丢失,创建时不需要使用mkfs等进行格式化。

  1. tmpfs的挂载:首先确定你的内核已经支持tmpfs

    mount -t tmpfs -o size=10M tmpfs /tmp

    df -h

    使用/etc/fstab条目:tmpfs /tmp tmpfs defaults 0 0

  2. tmpfs的使用:用来存放应用临时生成的信息,不需要持久保存
    正常使用挂载目录:创建文件,存储信息,删除文件等
    记住:目录下的所有信息将在系统掉电后全部丢失

  3. tmpfs的作用
    提高存储效率,内存的访问速度比Flash快很多
    避免对Flash存储设备的频繁读写,提高使用寿命

三、devfs
Linux2.6内核以前设备文件的抽象机制:提供了一种类似于文件的方法来管理位于/dev目录下的所有设备。

  1. /dev ————— 根文件系统目录
    设备文件创建
    制作根文件系统时创建基本的,比如console,tty1等
    设备驱动加载时创建相应的设备文件

  2. 特殊设备文件
    /dev/console
    /dev/null /dev/zero

  3. devfs的缺点 ————> sysfs的设计
    不确定的设备映射,有时一个设备映射的设备文件可能不同,例如我的U盘可能对应sda有可能对应sdb
    没有足够的主/辅设备号,当设备过多的时候,显然这会成为一个问题

四、sysfs
Linux2.6内核以后引入sysfs:挂载于/sys目录下,把实际连接到系统上的设备和总线组织成一个分级的文件,用户空间的程序同样可以利用这些信息以实现和内核的交互,该文件系统是当前系统上实际设备树的一个直观反应。

  1. sysfs的原理
    kobject子系统:建立目录树
    当一个kobject被创建的时候,/sys/目录下对应的文件和目录也就被创建
    每个设备在sysfs中都有唯一对应的目录,可以被用户空间读写

  2. sysfs的挂载:首先确定你的内核已经支持sysfs,默认支持

    mount -t none sysfs /sys

    使用/etc/fstab条目:none /sys sysfs defaults 0 0

  3. sysfs的使用
    cat命令: 查看/sys目录下的设备信息

  4. sysfs的应用
    用户空间的工具udev:利用了sysfs提供的信息来实现所有devfs的功能
    udev运行在用户空间中,而devfs却运行在内核空间

总结:
一切皆文件的抽象思想,使得Linux系统的管理变得简单统一,好的哲学产生好的设计。

Lession 10 嵌入式NFS文件系统的介绍与应用

嵌入式是宿主机 + 开发板的开发模式,两者之间的网络通讯与文件共享是进行高效率开发调试的前提条件。
NFS文件系统是嵌入式开发调试的快速高效手段,掌握与熟练使用是必备技能。

一、NFS简介
1、NFS:Network FileSystem
通过NFS挂载远程主机的目录,访问该目录就像访问本地目录一样
使用NFS服务能够方便地使各unix-like系统之间实现共享
Samba:在unix-like系统和windows系统之间共享

2、NFS模式:C/S模式,RPC服务框架
NFS Server <----------> NFS Client
NFS运行在SUN的RPC(Remote Procedure Call,远程过程调用)基础上,RPC定义了一种与系统无关的方法来实现进程间通信

  1. NFS服务与安装:
    portmap服务
    nfs-kernel-server服务
    安装:# sudo apt-get install nfs-kernel-server
    启动:# sudo /etc/init.d/nfs-kernel-server start
    停止:# sudo /etc/init.d/nfs-kernel-server stop
    状态:# sudo /etc/init.d/nfs-kernel-server status
    重启:# sudo /etc/init.d/nfs-kernel-server restart

二、NFS使用配置

  1. 配置文件: /etc/exports
    对NFS服务的访问是由exports来批准,它枚举了若干有权访问NFS服务器上文件系统的主机名。
    文件控制对目录的共享(NFS挂载目录及权限由该文件定义),书写规则是每个共享为一行)。

    格式:[共享目录] 主机名或IP
    第一个参数是要让客户机访问的目录,第二个是你允许的主机IP,最后的()内是访问控制方式。

  2. NFS共享控制参数:man exports
    ro 只读访问
    rw 读写访问
    sync 所有数据在请求时写入共享(默认)
    async NFS在写入数据前可以相应请求
    secure NFS通过1024以下的安全TCP/IP端口发送
    insecure NFS通过1024以上的端口发送
    wdelay 如果多个用户要写入NFS目录,则归组写入(默认)
    no_wdelay 如果多个用户要写入NFS目录,则立即写入,当使用async时,无需此设置
    hide 在NFS共享目录中不共享其子目录
    no_hide 共享NFS目录的子目录
    subtree_check 要求检查请求访问的目录或者文件是否在共享目录下
    no_subtree_check 只检查请求访问的目录或文件是否在共享的文件系统中
    all_squash 共享文件的UID和GID映射匿名用户anonymous,适合公用目录
    no_all_squash 保留共享文件的UID和GID(默认)
    root_squash root用户的所有请求映射成如anonymous用户一样的权限(默认)
    no_root_squash root用户具有根目录的完全管理访问权限
    anonuid=xxx 指定NFS服务器/etc/passwd文件中匿名用户的UID
    anongid=xxx 指定NFS服务器/etc/passwd文件中匿名用户的GID

  3. 配置命令
    exportfs
    重新加载/etc/exports的共享目录,卸载NFS Server共享的目录或者重新共享
    若更改了/etc/exports,运行以下命令进行更新:

    $ sudo exportfs -r
    

    showmount
    用來查看NFS共享的目录资源, 查看NFS Server的export list:

    $ sudo showmount -e
    

二、NFS开发板使用

1、宿主机防火墙:在挂载失败时返回来检查设置
一般需要关闭防火墙服务,确保没有屏蔽NFS使用的端口和允许通信的主机

2、NFS内核支持
Network FileSystem --> [] NFS Client
首先查看目标板kernel自身是否支持NFS

cat /proc/filesystems命令: 是否有NFS一行

3、NFS目录挂载
挂载格式: mount [Server IP]:/[share dir] [local mount point]

# mount -t nfs -o nolock 192.168.10.11:/opt/FriendlyARM/mini2440/root_nfs /mnt/root_nfs

检查挂载:挂载失败会有错误原因打印

# df -h

取消挂载

# umount /mnt/root_nfs

Lession 11 Ramfs文件系统:initramfs概念与使用

Linux内核加载根文件系统执行/sbin/init程序前,需要找到根设备位置,如果根设备需要驱动的支持,
内核有可能无能为力,通过提供一个过渡的临时根文件系统可以使得内核的设计更灵活简单。

一、rootfs,ramfs,ramdisk与tmpfs

  1. rootfs
    内核启动的初始始根文件系统,大部分linux系统正常运行后都会安装另外的文件系统,然后忽略rootfs
  2. ramfs
    基于内存的文件系统。ramfs文件系统没有容量大小的限制,它可以根据需要动态增加容量。
    直接利用了内核的磁盘高速缓存
  3. ramdisk
    基于ram的块设备,占据一块固定的内存,事先要使用特定的工具比如mke2fs格式化,还需要一个文件系统驱动来读写其上的文件
    空间固定导致容量有限,要想装入更多的文件需要重新格式化
    Linux的块设备缓冲特性, ram disk上的数据被拷贝到page cache(对于文件数据)和dentry cache(对于目录项),导致内存浪费
  4. tmpfs
    ramfs的一个缺点是它可能不停的动态增长直到耗尽系统的全部内存,所以只有root或授权用户允许使用ramfs。
    增加了容量大小的限制 + 允许把数据写入交换分区
    由于增加了这两个特性,tmpfs允许普通用户使用。

二、initrd与initramfs
过渡根文件系统机制:将加载真正的根文件系统需要的设备驱动、工具以及初始化程序先加载到内存运行。

  1. initrd: initial Ramdisk
    /linuxrc文件
    基于ramdisk技术
    文件系统(ext2等)镜像文件 ————> cpio格式镜像文件
    在内核启动完成后把它复制到/dev/ram块设备中, 作为内核加载真正根文件系统的过渡根文件系统

  2. initramfs: initial RAM file system
    init文件
    cpio格式镜像文件
    在内核启动完成后把它复制到rootfs中,作为内核初始的根文件系统,完成挂载系统真正的根文件系统

三、initramfs使用

  1. init程序文件: hello world
    #include

    int main(int argc, char *argv[])
    {
    printf("Hello world Initramfs!\n");
    sleep(999999999);
    }
    交叉编译:arm-linux-gcc -static hello.c -o hello
    修改命名:mv hello init

  2. 打包initramfs镜像
    find .|cpio -o -H newc|gzip > ~/myinitramfs.cpio.gz
    在内核中选择使用: 注意选择initramfs的压缩格式

  3. 解包initramfs镜像
    cpio -i -F myinitramfs.cpio --no-absolute-filenames
    zcat myinitramfs.cpio.gz | cpio -i -d -H newc --no-absolute-filenames

  4. 内核initramfs的构建
    General setup --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
    (/rootfs_dir) Initramfs source file(s)
    Built-in initramfs compression mode (None) ---> [] None [] GZIP

总结:
Linux内核 ————> initrd/initramfs(包含根文件系统的设备驱动等) ————> Real Root Filesystem
详细官方的描述文档:内核源码树下 Documentation/filesystems/ramfs-rootfs-initramfs.txt

Lession 13 Flash文件系统:jffs/jffs2和yaffs/yaffs2

在嵌入式系统中进行数据读写时,为了保证可靠性,我们可以选择哪些合适的文件系统?

一、Flash闪存类型
非易失存储器,可以对称为块的存储器单元块进行擦写和再编程
任何flash器件的写入操作只能在空或已擦除的单元内进行,在进行写入操作之前必须先执行擦除

  1. NOR Flash: 非易失内存
    应用:代码存储介质
    特点:
    芯片内执行(XIP, eXecute In Place)
    低容量高成本: 1 - 16MB(常见)
    读写速度:读取速度快,写入速度慢
    块最大擦写次数:10W

  2. NAND Flash:类似硬盘的块设备
    应用:数据存储介质
    特点:
     极高的单元密度
    读写速度:写入和擦除的速度很快
    高容量低成本:16 - 1024MB(常见)
    块最大擦写次数:100W

二、JFFS2
JFFS:1999
Journalling Flash File System, Version 2:2001-9-23,Linux 2.4.10
主要用于NOR Flash,可用于NAND Flash

  1. 特性:
    掉电保护与损耗平衡
    垃圾回收机制
    CRC循环冗余校验机制
    挂载时间与内存消耗跟文件系统的大小成正比:文件系统越大,越慢,消耗越多 ————> 很差的扩展性
    挂载需要进行全盘扫描,挂载一个 16M 的闪存有时需要半分钟以上的时间
    在实际应用中,JFFS2 最大能用在 128M 的闪存上


三、YAFFS2
YAFFS:2002
Yet Another Flash File System, Version 2:2003
只能用于NAND Flash, YAFFS1支持512Bytes/Page的NAND Flash;YAFFS2支持2kBytes/Page的NAND Flash.

1.特性:

储存资料的基本单位是Chunk:Page
支持YAFFS/Direct使用:可以不需要VFS,甚至操作系统支持
ECC冗余校验机制
  纠正单比特错误和检测双比特错误,而且计算速度很快,但对1比特以上的错误无法纠正,对2比特以上的错误不保证能检测。
更快的挂载速度,更少的内存使用
  512B/page ————> 4KB RAM/1MB NAND
  2KB/Page  ————> 1KB RAM/1MB NAND

总结:
JFFS与YAFFS都是日志结构文件系统(LFS),保障了数据的可靠性与安全性,可以恢复数据。
一般来说,对于小于64MB的NAND Flash,可以选用JFFS2;如果超过64MB,用YAFFS2比较合适

Lesson 16 Cramfs文件系统的制作与使用

如何来制作一个cramfs文件系统的镜像以及验证它?

一、工具安装
sudo apt-get install cramfsprogs

命令:

mkcramfs
cramfsck

二、镜像制作
文件系统内容:mini_busybox/
mkcramfs [dir] [fs-name]

三、镜像使用
文件系统验证:

cramfsck  [fs-name]

文件系统测试:losetup命令

losetup [loop device] [fs-file]
losetup -a
losetup -d [loop device]

总结:文件系统镜像制作:安装工具 --- 准备文件系统内容 --- 使用工具制作镜像 --- 测试镜像

Lesson 17 squashfs文件系统的制作与使用

如何来制作一个squashfs件系统的镜像?

一、工具安装
sudo apt-get install squashfs-tools

命令:dpkg -L squashfs-tools|grep bin

mksquashfs
unsquashfs

二、镜像制作
mksquashfs source1 source2 ... dest [options] [-e list of exclude dirs/files]
主要选项:

-comp <comp>            指定压缩算法:gzip (default)/lzo/xz
-b <block_size>         设置块大小,单位 Bytes,默认 131072 bytes (1MB)
-no-exports             不支持NFS文件系统导出
-no-sparse              不检测稀疏文件
-no-xattrs              不存储扩展文件属性(XATTR)
-xattrs                 存储扩展文件属性(default)
-noI                    不压缩Inode节点表
-noD                    不压缩数据块
-noF                    不压缩片段块
-noX                    不压缩扩展文件属性
-no-fragments           不使用片段管理
-always-use-fragments   对比块大小大的文件也是用片段块
-no-duplicates          不对文件重复进行检查
-all-root               修改所有的文件拥有者为root
-force-uid uid          设置所有文件的uid为指定的uid
-force-gid gid          设置所有文件的gid为指定的gid
-nopad                  不对文件系统进行4K字节对齐
-keep-as-directory      如果指定的源中有目录,在文件系统中创建根目录包含该目录,而不是包含目录内容

文件系统内容:mini_busybox/

mksquashfs mini_busybox rootfs.squashfs -no-exports -no-xattrs -all-root

三、镜像使用
内容提取:

unsquashfs [options] filesystem [directories or files to extract]
主要选项:
  -d[est] <pathname>      解压到指定目录,默认为"squashfs-root"
  -n[o-progress]          不显示进度条
  -no[-xattrs]            不提取xattr属性,默认提取
  -l[s]                   列出文件系统内容,不进行解压缩提取

  unsquashfs rootfs.squashfs

烧录挂载:

sudo losetup /dev/loop0 rootfs.squashfs
sudo mount /dev/loop0 /mnt
sudo losetup -a

卸载解依附:

sudo umount /dev/loop0
sudo losetup -d /dev/loop0

Lession 18 jffs2文件系统的制作与使用

如何来制作一个jffs2文件系统的镜像?

一、工具安装
sudo apt-get install mtd-utils

命令:mkfs.jffs2

二、镜像制作
信息收集:

Flash的页大小、擦除块大小

mkfs.jffs2 [options]
主要选项:

  -p, --pad[=SIZE]        使用0xff填充文件系统到指定大小,不指定则只填充完最后一个擦除块
  -r, -d, --root=DIR      使用指定的目录内容构建文件系统(default: cwd)
  -s, --pagesize=SIZE     使用指定的页大小(最大数据节点大小) (default: 4KiB)
  -e, --eraseblock=SIZE   指定擦除块的大小 (default: 64KiB)
  -c, --cleanmarker=SIZE  擦除标记的大小 (default 12)
  -m, --compr-mode=MODE   选择压缩模式(default: priortiry)
  -x, --disable-compressor=COMPRESSOR_NAME  禁用指定的压缩算法
  -X, --enable-compressor=COMPRESSOR_NAME 启用指定的压缩算法
  -y, --compressor-priority=PRIORITY:COMPRESSOR_NAME  设置压缩算法的优先级
  -L, --list-compressors  列出可用的压缩算法
  -t, --test-compression  测试压缩算法
  -n, --no-cleanmarkers   不添加擦除标记到擦除块
  -o, --output=FILE       指定文件系统镜像名称(default: stdout)
  -l, --little-endian     创建一个小端的文件系统
  -b, --big-endian        创建一个大端的文件系统
  -q, --squash            压缩权限和设置所有文件的拥有者为root
  -U, --squash-uids       设置所有文件的拥有者为root
  -P, --squash-perms      压缩所有文件的权限

文件系统内容:mini_busybox/

mkfs.jffs2 -d mini_busybox --pad=0x1000000 -s 4096 -l -o rootfs.jffs2

三、镜像使用
MTD设备文件系统: 无法使用/dev/loop0块设备来模拟

只能在Flash设备上使用

应用: 烧录到Flash设备或者分区

总结:mtd-utils包带有很多的工具命令可以使用,辅助管理和使用Flash设备

Lession 19 yaffs2文件系统的制作与使用

如何来制作一个yaffs2文件系统的镜像?

一、获取yaffs2源码
git clone git://www.aleph1.co.uk/yaffs2
从源码中编译制作工具:

cd yaffs2/utils
make
  error: unknown type name ‘u8’
  error: unknown type name ‘u32’

  修改yportenv.h文件,增加:#define CONFIG_YAFFS_DEFINES_TYPES

制作工具:

mkyaffs2image: YAFFS2(2KB/page)
mkyaffsimage: YAFFS(512B/page)

二、镜像制作
文件系统内容:mini_busybox/
mkyaffs2image dir image_file [convert]

三、镜像使用
MTD设备文件系统: 无法使用/dev/loop0块设备来模拟

只能在NAND Flash设备上使用

应用: 烧录到Flash设备或者分区

Lession 20 文件系统移植实践三:Flash分区与文件系统镜像烧录

如何将文件系统镜像烧录到嵌入式Flash设备中,怎么样进行Flash的布局?

一、Flash设备分区

  1. 嵌入式通用Flash布局
    bootloader + kernel + rootfs + appfs

  2. 内核启动参数bootargs: mtparts
    mtdparts: mtdparts=mtd-id:@(),@()
    mtdparts=s5pv210-nand:1M(boot),5M(kernel),80M(rootfs),426M(usrfs)
    mtdparts=s5pv210-nand:1M(boot),5M(kernel),80M(rootfs),16M(jffs2),394M(yaffs2)
    要想这个参数起作用,内核中的mtd驱动必须要支持,即内核配置时需要选上
    Device Drivers ---> Memory Technology Device (MTD) support ---> Command line partition table parsing

    0x000000000000-0x000000100000 : "boot"
    0x000000100000-0x000000600000 : "kernel"
    0x000000600000-0x000005600000 : "rootfs"
    0x000005600000-0x000006600000 : "jffs2"
    0x000006600000-0x000020000000 : "yaffs2"

二、uboot环境下的Flash命令
nand - NAND sub-system

nand info - show available NAND devices
nand device [dev] - show or set current device
nand read - addr off|partition size
nand write - addr off|partition size

read/write 'size' bytes starting at offset 'off'
to/from memory address 'addr', skipping bad blocks.

nand write.yaffs - addr off|partition size

write 'size' bytes starting at offset 'off' with yaffs format
from memory address 'addr', skipping bad blocks.

nand erase[.spread] [clean] off size - erase 'size' bytes from offset 'off'

With '.spread', erase enough for given file size, otherwise,
'size' includes skipped bad blocks.

二、文件系统镜像烧录

  1. 镜像制作: Flash型号的Page大小与Block大小,查看Datasheet手册
    K9F4G08X0B Array Organization:
    1 Page = (2K + 64)Bytes
    1 Block = 64 Pages = (128K + 4K) Bytes

    mkfs.jffs2 -d mini_busybox --pad=0x1000000 -s 2048 -e 0x20000 -l -o rootfs_128K.jffs2

  2. 下载镜像到系统内存中: 确定内存地址
    tftp 0x20008000

  3. 确定烧录要使用的分区: 确定Flash地址
    Flash地址偏移
    0x000005600000-0x000006600000 : "jffs2"
    0x000006600000-0x000020000000 : "yaffs2"

  4. 烧录内存中的镜像到Flash分区中
    nand erase[.spread]
    nand write
    nand write.yaffs

完整命令:
tftp 0x20008000 rootfs.jffs2;nand erase 0x5600000 0x1000000;nand write 0x20008000 0x6600000 0x1000000
tftp 0x20008000 rootfs.yaffs2;nand erase 0x6600000 0x19a00000;nand write.yaffs 0x20008000 0x6600000 0x4194c0

Lession 21 文件系统的挂载配置与选项

将Flash设备分区挂载到根文件系统才能进行读写操作,挂载动作是系统正常运行的基础工作。

一、根文件系统与应用文件系统
根文件系统挂载: 内核完成
应用文件系统(设备分区)挂载:mount命令

Linux伪文件系统
tmpfs文件系统
Flash设备分区

二、文件系统的挂载
准备工作:

设备分区:/dev/mtdblock3 /dev/mtdbock4
创建挂载点:/mnt  /tmp  /apps

挂载命令:

mount   系统当前的文件系统挂载信息
mount -a  挂载/etc/fstab文件中指定的文件系统与设备
mount -t <fstype> [options] <device name> <mount-point> 挂载指定类型的设备到指定挂载点
  mount -t jffs2 /dev/mtdblock3 /appfs/jffs2    ----> 时间比yaffs2的挂载长很多
  mount -t yaffs2 /dev/mtdblock4 /appfs/yaffs2

启动挂载控制:启动脚本设置

/etc/fstab   添加设备与文件系统的挂载配置
  注意:确保MTD设备分区已识别(udev/mdev的运行需要比/etc/fstab的挂载早)

/etc/init.d/rc.S  添加具体的设备挂载命令
  添加挂载脚本:
  mount -t jffs2 /dev/mtdblock3 /appfs/jffs2
  mount -t yaffs2 /dev/mtdblock4 /appfs/yaffs2

Lession 22 嵌入式开发文件系统的选择与配置原则

构建嵌入式软件开发的基础设施环境是嵌入式应用开发的前提

一、嵌入式软件开发

  1. uboot ———— 提供开发控制环境
    基础硬件驱动移植
    串口控制终端
    Flash设备
    网卡识别

  2. kernel(linux) ———— 系统管理与任务调度
    完整硬件驱动移植
    文件系统支持移植

  3. FileSystem(rootfs + appfs) ———— 提供用户应用环境
    移植构建根文件系统
    组织应用文件系统
    应用开发

  4. 分区管理控制
    uboot + kernel + fs
    镜像制作与烧录

二、文件系统移植应用

  1. 应用范畴
    根文件系统:建立用户空间使用环境
    busybox -----> 提供系统管理等全面的用户工具集合
    启动脚本 -----> 配置用户空间的环境变量与提供应用开机启动机制

    应用文件系统:存放用户应用程序与数据
    防止修改: cramfs squashfs
    Flash设备: jffs2 yaffs2
    SD卡等外部设备:FAT32

    临时文件系统:运行时存在的文件系统
    系统信息管理:Linux伪文件系统

    proc
    sys
    

    内存文件系统:临时数据的存放管理

    tmpfs
    

总结:内核与文件系统是嵌入式软件开发的基础设施,最重要的原则就是必须保证稳定可靠。

`