JFFS2 是一個開放源碼的項目(www.infradead.org)。 它是在閃存上使用非常廣泛的讀/寫文件系統,在嵌入式系統中被普遍的應用。
1. 安裝mkfs工具
MTD主頁:http://www.linux-mtd.infradead.org/archive/index.html
下載MTD:ftp://ftp.uk.linux.org/pub/people/dwmw2/mtd/cvs/
1.1. 配置參數
下載好MTD軟件,解壓后
$ make menuconfig
按需要配置參數,下邊是在網上搜索到的一個配置方案:
進入 Memory Technology Devices (MTD) --->
<*> Memory Technology Device (MTD) support
[*] Debugging
[*] MTD partitioning support
[*] Command line partition table parsing
[*] Direct char device access to MTD devices
[*] Caching block device access to MTD devices
RAM/ROM/Flash chip drivers ----->
<*> Detect non-CFI AMD/JEDEC-compatible flash chips
<*> Support for AMD/Fujitsu flash chips
Mapping drivers for chip access --->
[*] Support non-linear mappings of flash chips
Self-contained MTD device drivers --->
[*] Support for AT45... DataFlash
NAND Flash Device Drivers ---->
[*] NAND Device Support
[*] Support for NAND Flash /SmartMedia on AT91
File systems ---->
<*> Second extended fs support
[*] Inotify file change notification support
[*] Inotify support for user space
<*> Filesystem in Userspace support
Miscellaneous filesystems
<*> Journalling Flash File System v2 (JFFS2) support
[*] JFFS2 write-buffering support
<*> Compressed ROM file system support (cramfs)
以上配置中沒有列出的,都沒選;其配置僅做參考,可根據自己的需要自行配置。
$ make all
1.2. 安裝zlib庫
由於交叉編譯mtd工具時需要zlib.h文件,所以在編譯之前先安裝zlib庫文件。從網上下載zlib-1.2.3.tar.gz解壓縮
$ tar zxvf zlib-1.2.3.tar.gz
$ cd zlib-1.2.3
$ ./configure –prefix=/usr/local/arm/arm-linux --shared
修改Makefile如下:
CC=gcc(由於我的mkfs.jffs2是在宿主機下制作文件系統用的,因此不需要采用交叉編譯。下邊的LDSHARED也是一樣,不需要采用交叉工具)
LDSHARED=ld -shared
$ make all
$ make install
注意:這里是安裝在/usr/local/arm/arm-linux目錄下
1.3. 安裝mtd
從網上下載mtd-snapshot-20050519.tar.bz2 解壓縮
$ tar jxvf mtd-snapshot-*
$ cd mtd/util
修改該目錄下的Makefile:
SBINDIR=/usr/sbin
MANDIR=/usr/man
INCLUDEDIR=/usr/include
LDFLAGS=-L/usr/local/arm/arm-linux/lib #zlib庫的庫文件所在文件夾
CROSS= #用於宿主機下
CC := $(CROSS)gcc
CFLAGS := -I../include -I/usr/local/arm/arm-linux/include -O2 -Wall
$ make all
(加上-I/usr/local/arm/arm-linux/include是因為,在編譯的過程中出現找不到zlib.h的錯誤,加上LDFLAGS也還是有同樣的錯誤,所以直接在CFLAG中加上zlib庫文件所在的文件夾的位置。)
然后將該目錄下生成的 flash_erase,flash_eraseall, mkfs.jffs2工具放在ramdisk文件系統中(我這里放在/bin目錄下)。另外,需要將/arm-linux/lib目錄下的libz.so, libz.so.1, libz.so.1.2.3文件拷貝到ramdisk文件系統的/lib目錄下,否則mkfs.jffs2工具不能使用。
2. 掛載、制作jffs2文件系統
在這里,為了避免重新制作文件系統,我采用了英蓓特公司的MBS-SAM9G45開發板自帶的jffs2文件系統Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2。在整個制作jffs2文件系統的過程中,我們采用root權限。
2.1. 掛載文件系統鏡像
jffs2文件系統不是塊設備,不能直接mount,需要做一些中間步驟。首先,內核必須支持MTD,並且編譯了mtdram、mtdblock這兩個模塊。先先建立一個大於等於要掛載的文件系統的虛擬mtd設備。Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2文件系統為28.2M,那么我先建立一個大於等於28.2M的虛擬mtd設備。(為了避免制作過程當中向文件系統里邊添加大文件,我將mtd大小設置為50M*1024=50720K)
$ sudo modprobe mtdram total_size=50720
其中,total_size的單位是KB,指定mtd的大小。
加載mtdblock產生虛擬塊設備並把Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2的內容寫入生成的虛擬設備中:
$ sudo modprobe mtdblock
$ sudo dd if=/home/Embest_SAM9G45/Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2 of=/dev/mtdblock0
(注:dd命令是指定大小的塊拷貝文件,並在拷貝的同時進行指定的轉換。if=file:輸入文件名,缺省為標准輸入。of=file:輸出文件名,缺省為標准輸出。)
創建掛載點:
$mkdir /mnt/mtd
現在就可以mount了:
$ sudo mount -t jffs2 /dev/mtdblock0 /mnt/mtd
進入/mnt/mtd之后即可對文件系統進行修改!
2.2. 制作jffs2文件系統鏡像
修改(在后邊一步講)好自己的文件系統后,退到已做好的文件系統目錄的上一級。比如我的文件系統的掛載點是/mnt/mtd,則退到/mnt目錄下,用mkfs.jffs2工具制作jffs2文件系統,如下:
#mkfs.jffs2 -r rootfs -o fs.jffs2 -e 0x20000 --pad=0x500000 -s 0x800 –n -l
即可生成 rootfs.jffs2
Mkfs.jffs2各參數的意義如下:
-r:指定要做成image的目錄名。
-o:指定輸出image的文件名。
-e:每一塊要擦除的block size,默認是64KB.要注意,不同的flash, 其block size會不一樣,三星的K9F2G08U0A的block size為0x20000(從其datasheet里可以找到)。在沒有加-e選項是,啟動會出現以下錯誤:at91sam user.warn kernel: Empty flash at 0x00f0fffc ends at 0x00f10000。因此,若有類似的錯誤,加上-e選項,並配置nandflash的塊大小,即可消除。
--pad(-p):用16進制來表示所要輸出文件的大小,也就是fs.jffs2的大小,如果實際大小不足此設定的大小,則用0xFF補足。也可以不用此選項,生成的文件系統的大小跟本身大小一致,暫時還不知道有和妙用,但是加上后會少出現很多錯誤。
-n,-no-cleanmarkers:指明不添加清楚標記(nandflash有自己的校檢塊,存放相關的信息)。如果掛載后會出現類似:CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0的警告,則加上-n就會消失。
-l,--little-endian:指定使用小端格式。
還有的選項,不需要了,可以自己看幫助!用如下命令mkfs.jffs2 –h。
3. 修改文件系統 3.1. 需要修改的原因
1、 系統在啟動時,會啟動很多的項目,而很多的進程是我們根本不需要的,通過對文件系統的修改,可以減少啟動項,加快開機速度。
2、 由於開發板提供的文件系統很全面,囊括了聲卡、顯卡、游戲、液晶顯示屏等很多驅動,但是這些都是我所不需要的,因此通過修改文件系統,我們可以裁減掉不需要的驅動、庫文件以及所有的配置文件。
3、 在系統啟動時,需要加入我們自己啟動程序。在這個文件系統中,加入了超級用戶自動登錄功能、無線網卡驅動自啟動以及和FPGA的接口驅動自動加載。
3.2. 刪除多余的啟動項
所有的啟動項都在init.d中實現,按照不同的runlevel,分布在rc0.d~rc6.d以及rcS.d中。rc?.d和/etc/init.d的關系,在下邊這篇文章中敘述的相當詳細,可以參考學習:
http://wenku.baidu.com/view/8bdb9237ee06eff9aef8071b.html
rc?.d中都是指向/etc/init.d中腳本的連接。在rc?.d中,可以看到有K和S開頭的兩種連接。S開頭表示啟動,K開頭表示不啟動。在啟動時,系統會執行rc?.d中的所有S開頭的所指向的腳本文件。因此,我們只需要修改rc?.d中的連接以及/etc/init.d中的腳本文件,就可以修改啟動的項目。
在本文件系統中,我做了如下修改:
rc2.d:關閉S50usb-gadget。
rc3.d:關閉S50usb-gadget、S10alsa-state、S10dropbear。
rc4.d:關閉S50usb-gadget。
rcS.d:關閉S00psplash(旋轉進度條,顯示開機的進度)、S02banner。
我用的關閉的方法是mv S50usb-gadget K50usb-gadget,這樣就關閉了usb-gadget,在需要啟動此項時,也很方便啟動。當然,這樣的操作並沒有大幅度減小啟動的時間。
3.3. root用戶自動登錄
在每次設備啟動或者復位的時候,都需要手動在啟動結束后輸入root以登錄系統,而在無人值守的情況下,需要root用戶能自動登錄,並執行程序。在/etc/inittab中做如下修改即可實現root用戶自動登錄:
默認啟動runlevel為5,即id: 5 :default
注釋掉登錄的那行代碼,即#S:2345:respawn:/sbin/getty 115200 ttyS0
添加如下登錄代碼:S1:2345:respawn:/sbin/getty /usr/bin/autologin 115200 ttyS0。啟動autologin程序需要自己完成,/usr/bin/是autologin所在位置,這個位置可以自己任意選取。
編寫autologin.c程序如下:
| #include #include
int main ( ) { execlp(“login”, “login”, “-f”, “root”, 0); } |
然后編譯autologin.c,注意要使用交叉編譯器。
$ /usr/local/arm-2007q1/bin/arm-none-linux-gnueabi-gcc –o autologin autologin
將編譯好的autologin可執行文件復制到/usr/bin目錄下。也可以放到其他目錄下,相應的修改/etc/inittab即可。
至此,重新制作文件系統鏡像后,燒寫進nandflash,即可自動登錄root用戶。
3.4. 添加自己的啟動項
因為rcS是每個系統都必須啟動的項,因此在rcS中添加啟動項是最直接的方法。(在我們的系統的中沒有rc.local文件,網上有很多在rc.local中添加自啟動的方法)
我需要自動加載無線網卡驅動、FPGA接口驅動以及開啟DHCP服務。
首先,將無線網卡和FPGA的驅動以及DHCP的可執行文件以及配置文件拷貝進相應的文件夾(可執行放的文件夾可以自己設置,在寫執行腳本的時候注意路徑,配置文件需要按規則放)。在這里,我將無線網卡驅動rt3070sta.ko拷貝到/usr/src中,rt3070sta.ko驅動加載后需要讀取的配置文件RT2870STA.dat放在/etc/Wireless/RT2870STA中。將FPGA的接口驅動fpgadev拷貝到/usr/src。在編譯內核時,已經添加了dhcp服務,因此在/sbin和/usr/sbin中分別放有客戶端uhdpc和服務端uhdpd,拷貝配置文件udhcpd.conf到/etc下,在/var/lib/misci下新建(touch命令)一個文件udhcpd.leases。修改所有文件的權限為755(chmod 755 xxx)。
其次,需要在/etc/init.d中添加執行的腳本文件,在此腳本文件中添加你要執行的代碼。編寫autoset_sta腳本如下:
| #!/bin/sh
#Auto set wireless card and FPGA driver /sbin/insmod /usr/src/rt3070sta.ko /sbin/insmod /usr/src/fpgadev.ko\
/sbin/udhcpc |
最后,修改文件權限並在rcS.d中添加指向init.d/autoset_sta的連接。
$ chmod 755 autoset_sta
$ cd ../rcS.d
$ ln –sf ../nit.d/autoset_sta S99autoset_sta
制作好文件系統后,燒寫重啟即可自動加載這些驅動以及服務。
3.5. 減小文件系統體積
原始文件系統28.2MB,在加上自己的文件后,達到了30MB。嵌入式下存儲資源是寶貴的,為了減少所占資源,必須對文件系統進行瘦身。
進入/etc,刪除不必要的啟動腳本文件,比如X11的文件。
進入/lib,刪除比需要的庫文件。
進入/usr,刪除games。
進入/usr/bin,刪除沒用的命令。
進入/usr/lib,刪除沒用的庫文件。這里庫文件相當多,達到16M之巨,而里邊大多是我們不用的庫,例如libaudiofile.so.0、libsoundgen.so.0、libmad*、libICE等,還有關於圖像和界面的庫等,這些都可以刪掉。全部刪除后,/usr/lib可以小到3M~6M。當然,這都得看具體應用,對與我來講,我所用到的就是網絡編程、多線程、無線網卡、SPI通信、串口通信等東西,所以能刪除很多不必要的庫。但是因為啟動項刪除的不夠干凈,在啟動的過程當中,仍然會用到/usr/lib中的很多庫,因此會出現很多錯誤,但並不影響我的操作。
進入/usr/share,刪除沒有用的doc以及applications。。。。。
基本裁剪已經差不多了,重新編譯文件系統,輸出的大小為16M左右。
(還需要好好把系統的整個啟動已經程序的調用搞清楚一下,這還可以大大的裁剪)
4. 問題及解決方法
Q:在啟動過程中出現at91sam user.warn kernel: Empty flash at 0x00f0fffc ends at 0x00f10000問題
A:在mkfs.jffs2的時候,加上-e 0x20000指定擦除塊的大小。-e是指定擦除塊的大小,我們使用的nandflash的塊大小為128K字節,因此-e后的參數為(128*1024)10=(20000)16。
Q:啟動的時候出現CLEANMARKER node found at 0x00f10000 has totlen 0xc != normal 0x0問題。
A:在mkfs.jffs2的時候,加上-n選項。-n, --no-cleanmarkers。指明不添加清楚標記(nand flash 有自己的校檢塊,存放相關的信息。)如果掛載后會出現類似:CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0 的警告,則加上-n 就會消失。
Q:解決jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x01649298: 0xa25e instead問題的方法
A:在mkfs.jffs2的時候加上-s 2048(頁大小,由芯片決定)以及-l(小端模式)兩個選項。-s是指明頁的大小,我們使用的nandflash的頁的大小為2048字節。-l指明為小端模式,一般嵌入式下均為小端模式。
說明:
1、 在文件系統制作的過程,均需要使用root用戶權限;
2、 一般嵌入式下只有root用戶登錄,因此文件系統中的所有文件都需要具有root可執行權限,如果用其他用戶登錄,請保證文件系統中文件(特別是自己添加的文件)的相應可執行權限。
還不清楚的問題:
1、 啟動過程還不明白
2、 如何更有效的減少啟動時間?
http://blog.chinaunix.net/uid-23208702-id-353022.html
--------------------------------------------------------------------------------------------------------------------------------------------
1)zlib的編譯
tar xjvf zlib-1.2.3.tar.bz2
tony@Ubuntu:~/win/zlib-1.2.3$./configure
tony@Ubuntu:~/win/zlib-1.2.3$make
tony@Ubuntu:~/win/zlib-1.2.3$sudo make install
2)mtd工具的編譯
tar xjvf mtd-snapshot-20050519.tar.bz2
tony@Ubuntu:~/win/mtd/util$make
tony@Ubuntu:~/win/mtd/util$sudo make install
執行完上面2部,我們的系統里就有了mkfs.jffs2這個工具了
3)jffs2文件系統鏡像制作 (/opt/filesystem/目錄下為已經制作好的文件系統,參看--》根文件系統制作)
tony@Ubuntu:/opt$sudo mkfs.jffs2 -r filesystem -o filesystem.jffs2
tony@Ubuntu:/opt$cp filesystem.jffs2 /tftpboot/
4)將jffs2文件系統燒寫到nand
tftp 30008000 filesystem.jffs2
nand erase 500000 800000
nand write 30008000 400000 實際大小
setenv bootargs root=/dev/mtdblock2 init=/linuxrc rootfstype=jffs2 rw console=ttySAC0,115200
http://blog.csdn.net/ypist/article/details/7106019
