转载连接:http://kinglaw05.blog.163.com/blog/static/596833142010450154463/
根文件系统是Linux内核启动后第一个挂载的文件系统。在根文件系统中存放着内核镜像、各种系统配置文件以及一些其他的重要文件(例如设备文件、命令程序等)。为了保证通用性,根文件系统的目录结构需要遵守FHS(文件系统层次标准)标准(FilesystemHierarchy Standard)。FHS标准定义了根文件系统中每个目录名称及其作用的规则规范。如下所示的是一个符合FHS标准的根文件系统:
目录 内容
/ 根目录,其他目录都在这个目录下
/bin 存放基本命令的可执行文件,可被root与一般账号所使用
/sbin 存放基本系统管理类命令的可执行文件,root用户使用
/lib 存放共享库和可加载(驱动程序),共享库用于启动系统
/dev 存放设备与设备接口的文件
/etc 存放着系统主要的配置文件,root用户能修改
/usr 存放的是共享、只读的程序、数据和文档(用户的)
/usr/bin 存放用户程序可执行文件
/usr/sbin 存放用户系统管理类程序的可执行文件
/usr/lib 存放用户程序所需的共享库
/proc 用于挂载proc文件系统
/sys 用于挂载sysfs文件系统
tmp 存放临时文件
/var 存放系统日志及一些服务程序的临时文件
制作根文件系统的基本方法就是创建各个目录以及目录中的文件。创建目录是非常简单的,既可以通过命令mkdir来创建,也可以在图形界面直接创建。但命令方式比图形方式的效率要高。dev目录下存放的是各种设备文件。
1)控制台设备。控制台终端用于显示各种信息,显示器是一种最常见的控制台终端。在linux系统中,控制台的设备文件是console。控制台在其他设备驱动初始化前就可以使用,因此常用来显示内核的启动信息。
2)虚拟控制终端。为了满足多用户多任务的需要,可以通过虚拟控制终端来使用控制台终端。例如tty1、tty2、tty3文件等。
3)串口终端。串口终端是使用串行端口连接的终端设备。在Linux系统中常用的串口终端设备文件有ttyS0、ttyS1等。在Linux2.6内核中ttyS0文件称为ttySAC0。
串口终端可以被指定为控制台终端来使用。例如在内核启动参数中可以设置console=ttySAC0,也就是把串口终端设备ttySAC0作为控制台设备使用。
在嵌入式系统中,出于某种需要可能不希望动态创建设备文件,这时,所需的设备文件就要用mknod命令预先在根文件系统内创建,或者将创建设备文件的命令写入系统的初始化脚本中
step 1 创建目录和必要的设备文件。
step 2 安装所需的共享库。
step 3 交叉编译busybox
step 4 交叉编译bash
step 3 安装init文件、Shell和各种基本命令(可由busybox提供)。
step 4 创建和编辑配置文件。
一. 创建目录
[root@qljt1 /]# mkdir /jffs2 /jffs2/rootfs /jffs2/rootfs_build[root@qljt1 /]# cd /jffs2/rootfs
[root@qljt1 rootfs]# mkdir {bin,dev,etc,usr,lib,sbin,proc,sys,tmp}
[root@qljt1 rootfs]# mkdir usr/{bin,sbin,lib}
二. 拷贝动态链接库
[root@qljt1 rootfs]#cd /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib[root@qljt1 lib]# cp -arfv * /jffs2/rootfs/lib/
libc: 该库是C应用程序必须使用的基本C函数库。
ld-linux: 该库是动态链接器,提供动态链接函数
这里-a参数用来保留文件的所有属性,否则cp命令将试图从设备文件中读取内容并写入新文件。
arm-linux-strip –s /root/rootfs/lib/lib
arm-linux-strip –s /root/rootfs/lib/lib*
一般来说,一个共享库会对应着一个包含真正内容的文件,同时有若干个符号链接指向它,这样做是为了便于管理。在复制共享库的时候尽量保持这一模式,将应用程序所需的符号链接与包含真正内容的共享库文件一起复制过去。
busybox是嵌入式系统中常用的一个软件包,它把许多常用的Linux命令都集成到一个单一的可执行程序中,几乎只需要这一个可执行程序加上Linux内核就可以构建一个基本的Linux系统。busybox忽略了许多不常用的功能,因此非常小巧,并且是完全模块化的,可以很容易地在编译时增加或删除其中包含的命令。
BusyBox最初是为Debian GNU/Linux安装盘编写的。其目标是在一张软盘上创建一个可以引导的Linux系统,用来制作安装盘。
一张软盘的容量大约为1.4MB,所以并没有多少空间留给Linux内核以及文件系统。为此BusyBox提出了合并命令程序文件的思想。通过这个方法可以把3.5MB大小的命令程序包(也就是bin目录)压缩到只有200KB大小。为此,BusyBox获得了“瑞士军刀”的美誉。
根据这个原理,BusyBox把bin目录下常用命令程序的代码集成到一个busybox文件中。使得busybox文件中不会重复相同功能的代码。然后BusyBox为busybox文件创建了多个链接文件,每个链接文件表示一个命令程序(链接文件的名称就是各个命令程序的名称)。BusyBox通过链接文件把具体命令传递给busybox,由busybox完成各个命令的运行任务。
此外,BusyBox还直接提供了etc目录下的主要配置文件,大大减轻了制作根文件系统的工作把busybox-1.15.2.tar.ba2 放到 /jffs2/rootfs_build目录下,转到该目录
[root@qljt1 rootfs_build]# tar -xjvf busybox-1.15.2.tar.bz2[root@qljt1 rootfs_build]# cd busybox-1.15.2
[root@qljt1 busybox-1.15.2]# vi Makefile
修改下面两行
ARCH ?= arm
CROSS_COMPILE ?=/usr/local/arm/4.3.2/bin/arm-linux- (这个视你的交叉编译工具所在路径而定)
[root@qljt1 busybox-1.15.2]# make menuconfig
Busybox Settings --->
Build Options --->
| +-------------------------------------------------------------------------+ |
| | [*] Build BusyBox as a static binary (no shared libs) |
| | [ ] Force NOMMU build | |
| | [*] Build with Large File Support (for accessing files > 2 GB) | |
| | () Cross Compiler prefix | |
| | () Additional CFLAGS
Installation Options --->
| | [*] Don't use /usr |
| | (./_install) BusyBox installation prefix (进入这一项)
填入 /jffs2/rootfs
这样编译好的busybox,安装以后就会自动保存到 /jffs2/rootfs目录下,不用复制了。
保存退出
Ubuntu和Busybox下用make menuconfig配置出错解决 链接http://blog.csdn.net/satiling/article/details/6965985
解决方法:
一种是如果您用的是Ubuntu系统 就安装这个包 sudo apt-get install libncurses5-dev
装完就好了;
第二种 如果您用的是rhel系列 就安装这个包 ncurses-devel这个包 就可以了
[root@qljt1 busybox-1.15.2]# make ;make install
*********************************************************可以不看 参考文件链接***************************************************************
可以看到,配置界面中把配置选项分成了BusyBox Settings和Applets两大部分
1)BusyBox Settings (BusyBox设置)
General Configuration。该选项是BusyBox的常规配置选项,一般不需要改动里面的默认设置。
Build Options。该选项用于设置BusyBox的编译方式。
Build BusyBox as a static binary。该选项用于选择是否使用静态编译方式。如果选择采用静态编译,则生成的busybox命令文件在运行时就不需要额外的函数库支持。为了简单起见,这里建议选择使用静态编译方式。
Build shared libbusybox。该选项用于选择是否编译BusyBox动态库。
Build with Large File Support (for accessing files > 2 GB)。该选项用于选择BusyBox是否支持容量大于2GB的文件系统。
Cross Compiler prefix。该选项用于设置交叉编译器的前缀。
Debugging Options。该选项用于设置BusyBox的调试方式。
Installation Options。该选项用于设置BusyBox制作的根文件系统的安装路径。
BusyBox Library Tuning。该选项用于设置BusyBox库的一些调整配置。
2)Applets (应用程序)
这部分配置选项用于选择需要BusyBox支持的命令程序。所有的命令都根据功能进行分类。如下图所示的是进入“Coreutils”菜单后的界面。配置界面的操作方式和Linux内核的配置方式是基本一样的。
输入命令“make”对BusyBox的源代码进行编译。编译完成后会在BusyBox的根目录下生成一个可执行文件busybox,如下所示:
测试BusyBox能否正常运行:
把ls作为busybox的参数,让busybox执行ls的功能。从结果看出,busybox执行了ls的功能列出了当前目录下的文件。
接着运行命令“makeinstall”进行安装。安装完毕后会在BusyBox的根目录下生成一个_install目录。在_install目录下有bin、sbin和usr目录以及一个linuxrc链接文件。bin和sbin目录中全是指向BusyBox命令文件的链接文件。如下所示。其中,symbolic link是符号链接的意思。
linuxrc也是一个指向busybox命令文件的链接文件,如下所示:
linuxrc是BusyBox提供的init程序,和/sbin/init程序的作用是相同的。如果要使用linuxrc程序,只需要在内核的启动命令参数中通过“init=linuxrc”进行设定。
一般情况下,BusyBox提供的配置文件能够满足大多数应用环境的需要。所以可以直接把_install目录以及/examples/bootfloppy/etc目录下所有的文件(包括各个子目录)复制到rootfs目录下,并覆盖原有的文件。
至此,根文件系统的基本架构就搭建好了,用户只需要根据实际需要再添加各种文件就可以了
************************************************************end************************************************************
把bash-3.2.tar.gz 放到 /jffs2/rootfs_build目录下,转到该目录
[root@qljt1 rootfs_build]# tar -xzvf bash-3.2.tar.gz
[root@qljt1 rootfs_build]# cd bash-3.2
[root@qljt1 bash-3.2]# ./configure --host=arm-linux (或 比较系统的可点击此链接:./configure–-host=arm-linux–-enable-static-link)
[root@qljt1 bash-3.2]#make
[root@qljt1 bash-3.2]# arm-linux-strip bash (arm-linux-strip -s bash)
[root@qljt1 bash-3.2]# cp bash /jffs2/rootfs/bin/
五. 建立系统配置文件
1. etc/inittab 文件
[root@qljt1 bash-3.2]# cd /jffs2/rootfs
[root@qljt1 rootfs]# vi etc/inittab
添加如下内容
#first: run the system script file
::sysinit:/etc/init.d/rcS
#second:run the local script file
::once:/etc/rc.local
#third run the bash shell prosecc
::respawn:/bin/bash#restart init process
::restart:/sbin/init
#umount all file system
::shutdown:/bin/umount -a –r
保存退出
[root@qljt1 rootfs]# chmod 777 etc/inittab
上面的这个inittab文件决定的启动流程是:
(1) 执行“/etc/init.d/rcS”脚本;
(2) 执行“/etc/rc.local”脚本;
(3) 执行“/bin/bash”交互程序,进入交换界面;
2. etc/init.d/rcS文件
[root@qljt1 rootfs]# mkdir etc/init.d
[root@qljt1 rootfs]# vi etc/init.d/rcS
内容:
#!/bin/sh
#mount fs
/bin/mount -t ramfs ramfs /tmp
/bin/mount -t proc proc /proc
/bin/mount -t sysfs sysfs /sys
******************************************************************参考********************************************************************
******************************************************************end********************************************************************
[root@qljt1 rootfs]# chmod 777 etc/init.d/rcS
3. etc/rc.local 文件
内容如下(由于还没有移植网卡驱动,所以暂时全部都注释掉了):
#!/bin/sh
# set ip
#/sbin/ifconfig lo 127.0.0.1 up
#/sbin/ifconfig eth0 172.22.60.223 netmask 255.255.0.0 up
#/sbin/route add default gw 172.22.60.1 eth0
保存退出
[root@qljt1 rootfs]# chmod 777 etc/rc.local
[root@qljt1 rootfs]# vi .bashrc
#!/bin/bash
# set env
export PATH=/bin:/sbin:/usr/bin
export LD_LIBRARY_PATH=/lib:/usr/lib
/bin/hello &
保存退出5. 添加一个hello world用户程序
[root@qljt1 rootfs]# cd /jffs2/rootfs_build/
[root@qljt1 rootfs_build]# vi hello.c
#include <stdio.h>
int main(void)
{
printf("hello world!\n");
return 0;
}
保存退出
[root@qljt1 rootfs_build]# arm-linux-gcc -o hello hello.c
[root@qljt1 rootfs_build]# cp hello /jffs2/rootfs/usr/bin/
六. 制作JFFS2根文件系统映像
制作JFFS2根文件系统需要用到MTD工具,其下载地址是: ftp://ftp.infradead.org/pub/mtd-utils/mtd-utils-1.0.0.tar.gz
编译后会生成mkfs.jffs2 ,把mkfs.jffs2复制到 /sbin目录下。然后:
[root@qljt1 rootfs]# cd /jffs2
[root@qljt1 jffs2]# mkfs.jffs2 -r rootfs -o rootfs.jffs2 -p -l -n -e 0x4000 (0x4000=16KB,ICETEK138:0x20000=128KB)
[root@qljt1 jffs2]# ls
rootfs rootfs_build rootfs.jffs2
rootfs.jffs2就是可用的jffs2根文件系统镜像。
-r 指定内含根文件系统的目录
-o 指定文件系统映象的输出文件名称
-p 表示在映像的结尾用0x0补全到block
-l 存储格式为小端格式
-n 每个擦除的block中不添加clreanmarker
-e 擦除block的大小
Uboot下设置传递给内核的命令行参数:
setenv bootargs root=/dev/mtdblock2 init=/sbin/init console=ttySAC0,115200 rootfstype=jffs2
七. 下载运行
VFS: Mounted root (jffs2 filesystem) on device 31:2.
Freeing init memory: 120K
Warning: unable to open an initial console. 到这里停止,不能进控制台,修改如下:
//以root用户执行,创建节点
[root@qljt1 jffs2]# cd /jffs2/rootfs/dev/[root@qljt1 dev]# mknod -m 660 console c 5 1
[root@qljt1 dev]# mknod -m 660 null c 3 0
[root@qljt1 dev]# cd /jffs2
重新生成 rootfs.jffs2 下载运行。
VFS: Mounted root (jffs2 filesystem) on device 31:2.
Freeing init memory: 120K到这里停止,不能进控制台,估计是bash暂时没有启动,修改如下:
[root@qljt1 jffs2]# cd /jffs2/rootfs/etc/init.d/
[root@qljt1 init.d]# vi rcS
加上如下内容:
/bin/sh
保存退出,重新生成 rootfs.jffs2 下载运行。
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
VFS: Mounted root (jffs2 filesystem) on device 31:2.
Freeing init memory: 120K
/bin/sh: can't access tty; job control turned off
#
虽然还有小小错误,以后慢慢再改,但总算能够出控制台了。
但是hello和bash程序都不能运行,原因是他们链接的时候用了动态库。
****************************************************************************************************************************************************8888
用mkfs.jffs2命令制作jffs2镜像文件
转载连接:http://www.embeddedlinux.org.cn/html/filesys/201101/27-1084.html
下载:
ftp://sources.redhat.com/pub/jffs2/mkfs.jffs2
或者使用命令:
apt-get install mtd-utils
命令使用实例:
mkfs.jffs2 -s 0x1000 -e 0x40000 -p 0x500000 -d rootfs/ -o jffs2.img
说明:
页大小0x1000 4k
块大小0x40000 256k
jffs2分区总空间0x500000即5M
当然生成的jffs2.img并没有一下子分配5M,还是实际大小0xc0000
mkfs.jffs2使用方法
选项含义(man a mkfs.jffs2)
mkfs.jffs2: Usage: mkfs.jffs2 [OPTIONS]
Make a JFFS2 file system image from an existing directory tree
Options:
-p, --pad[=SIZE] 用16進制來表示所要輸出檔案的大小,也就是root.jffs2的size。
很重要的是, 為了不浪費flash空間, 這個值最好符合flash driver所規劃的區塊大小。
如果不足则使用0xff来填充补满。
-r, -d, --root=DIR 指定要做成image的源資料夾.(默认:当前文件夹)
-s, --pagesize=SIZE 节点页大小(默认: 4KiB=0x1000)
-e, --eraseblock=SIZE 设定擦除块的大小为(默认: 64KiB=0x10000)
-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 指明不添加清楚标记(nand flash 有自己的校检块,存放相关的信息。)
如果挂载后会出现类似:
CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0
的警告,则加上-n 就会消失。
-o, --output=FILE 指定輸出image檔案的文件名.(default: stdout)
-l, --little-endian 指定使用小端格式
-b, --big-endian 指定使用大端格式
-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 将所有文件的拥有者设为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 显示这些文字
-v, --verbose Verbose operation
-V, --version 显示版本
-i, --incremental=FILE Parse FILE and generate appendage output for it
生成的rootfs.img可通过u-boot直接烧写至nand flash:
nand erase 0x200000 0x3e00000//擦写
tftp 0x30000000 rootfs.img//下载
nand write.jffs2 0x200000 $(filesize)//烧入
(二) 在linux的PC上挂载jffs2根文件系统映像
因为jffs2是构建于MTD设备上的文件系统,所以无法通过loop设备来挂载,但是可以通过mtdram设备来挂载。mtdram是在用RAM实现的MTD设备,可以通过mtdblock设备来访问。使用mtdram设备很简单,只要加载mtdram和mtdblock两个内核模块即可。这两个内核模块一般的linux内核发行版都有编译好的,直接用modprobe命令加载。
下面是具体步骤:
(1).加载mtdblock内核模块
modprobe mtdblock
(2).加载mtdram内核模块,将该设备的大小指定为jffs2根文件系统映像的大小,块擦除大小(即flash的块大小)指定为制作该jffs2根文件系统时“-e”参数指定的大小,缺省为64KB。下面两个参数的单位都是KB。
modprobe mtdram total_size=5120 erase_size=256
(3).这时将出现MTD设备/dev/mtdblock0,使用dd命令将jffs2根文件系统拷贝到/dev/mtdblock0设备中。
dd if=jffs2.img of=/dev/mtdblock0
(4).将保存了jffs2根文件系统的MTD设备挂载到指定的目录上。
mount -t jffs2 /dev/mtdblock0 /mnt/mtd
这之后就可以到/mnt/mtd目录查看、修改挂载的jffs2根文件系统了,修改后的jffs2根文件系统可以通过dd命令拷贝为一个jffs2的映像文件