製作嵌入式linux檔案系統(ramdisk,cramfs,squashfs)
阿新 • • 發佈:2019-01-02
一、什麼是檔案系統 (Filesystem);
A directory structure contained within a disk drive or disk area. The total available disk space can be composed of one or more filesystems. A filesystem must be mounted before it can be accessed. To mount a filesystem, you must specify a directory to act as the mount point. Once mounted, any access to the mount point directory or its subdirectories will access the separate filesystem.
二、主要嵌入式採用的檔案系統 ;
* Linux 中,rootfs 是必不可少的。PC 上主要實現有 ramdisk 和直接掛載 HD(Harddisk,硬碟) 上的根檔案系統;嵌入式中一般不從 HD 啟動,而是從 Flash 啟動,最簡單的方法是將 rootfs load 到 RAM 的 RAMDisk,稍複雜的就是 直接從Flash 讀取的 Cramfs,更復雜的是在 Flash 上分割槽,並構建 JFFS2 等檔案系統。
* RAMDisk 將製作好的 rootfs 壓縮後寫入 Flash,啟動的時候由 Bootloader load 到RAM,解壓縮,然後掛載到 /。這種方法操作簡單,但是在 RAM 中的檔案系統不是壓縮的,因此需要佔用許多嵌入式系統中稀有資源 RAM。
ramdisk 就是用記憶體空間來模擬出硬碟分割槽,ramdisk通常使用磁碟檔案系統的壓縮存放在flash中,在系統初始化時,解壓縮到SDRAM並掛載根檔案系統, 在linux系統中,ramdisk有二種,一種就是可以格式化並載入,在linux核心2.0/2.2就已經支援,其不足之處是大小固定;另一種是 2.4的核心才支援,通過,ramfs來實現,他不能被格式化,但用起來方便,其大小隨所需要的空間增加或減少,是目前linux常用的ramdisk技術.
* initrd 是 RAMDisk 的格式,kernel 2.4 之前都是 image-initrd,Kernel 2.5 引入了 cpio-initrd,大大簡化了 Linux 的啟動過程,附合 Linux 的基本哲學:Keep it simple, stupid(KISS). 不過cpio-initrd 作為新的格式,還沒有經過廣泛測試,嵌入式 Linux 中主要採用的還是 image-initrd。
* Cramfs 是 Linus 寫的很簡單的檔案系統,有很好的壓縮綠,也可以直接從 Flash 上執行,不須 load 到 RAM 中,因此節約了 RAM。但是 Cramfs 是隻讀的,對於需要執行時修改的目錄(如: /etc, /var, /tmp)多有不便,因此,一般將這些目錄做成ramfs 等可寫的 fs。
* SquashFS 是對 Cramfs 的增強。突破了 Cramfs 的一些限制,在 Flash 和 RAM 的使用量方面也具有優勢。不過,據開發者介紹,在效能上可能不如 Cramfs。這也是一種新方法,在嵌入式系統採用之前,需要經過更多的測試
三、建一個包含所有檔案的目錄 ;
1。建一個目錄rootfs 用來裝檔案系統
2。mkdir bin dev etc lib proc sbin tmp usr var
3. ln -fs bin/busybox linuxrc(使用busybox)
4. 到系統 /dev 把所有的device打一個包,拷貝到 dev下面(最省事的做法);或者使用mknod來自己建所需要的device,我自己用的如下:
crw-rw-rw- 1 root root 5, 1 2006-02-24 13:12 console
crw-rw-rw- 1 root root 5, 64 2006-02-24 13:12 cua0
crw-rw-rw- 1 root root 63, 0 2006-02-24 13:12 dk0
crw-rw-rw- 1 root root 63, 1 2006-02-24 13:12 dk1
drwxr-xr-x 2 root root 4096 2006-02-24 13:12 flash
brw-rw-rw- 1 root root 3, 0 2006-02-24 13:12 hda
crw-rw-rw- 1 root root 36, 10 2006-02-24 13:12 ipsec
crw-rw-rw- 1 root root 241, 0 2006-02-24 13:12 ixNpe
crw-rw-rw- 1 root root 1, 2 2006-02-24 13:12 kmem
crw-rw-rw- 1 root root 126, 0 2006-02-24 13:12 ledman
lrwxrwxrwx 1 root root 16 2007-09-19 14:08 log -> /tmp/var/log/log
crw-rw-rw- 1 root root 1, 1 2006-02-24 13:12 mem
crw-rw-rw- 1 root root 90, 0 2006-02-24 13:12 mtd0
brw-rw-rw- 1 root root 31, 0 2006-02-24 13:12 mtdblock0
brw-rw-rw- 1 root root 31, 1 2006-02-24 13:12 mtdblock1
brw-rw-rw- 1 root root 31, 2 2006-02-24 13:12 mtdblock2
brw-rw-rw- 1 root root 31, 3 2006-02-24 13:12 mtdblock3
brw-rw-rw- 1 root root 31, 4 2006-02-24 13:12 mtdblock4
brw-rw-rw- 1 root root 31, 5 2006-02-24 13:12 mtdblock5
brw-rw-rw- 1 root root 31, 6 2006-02-24 13:12 mtdblock6
crw-rw-rw- 1 root root 90, 1 2006-02-24 13:12 mtdr0
crw-rw-rw- 1 root root 1, 3 2006-02-24 13:12 null
crw-rw-rw- 1 root root 108, 0 2006-02-24 13:12 ppp
crw-r--r-- 1 root root 5, 2 2006-03-29 15:56 ptmx
drwxr-xr-x 2 root root 4096 2006-03-29 15:56 pts
crw-rw-rw- 1 root root 2, 0 2006-02-24 13:12 ptyp0
brw-rw-rw- 1 root root 1, 0 2006-02-24 13:12 ram0
crw-rw-rw- 1 root root 1, 8 2006-02-24 13:12 random
crw-rw-rw- 1 root root 5, 0 2006-02-24 13:12 tty
crw-rw-rw- 1 root root 4, 0 2006-02-24 13:12 tty0
crw-rw-rw- 1 root root 3, 0 2006-02-24 13:12 ttyp0
crw-rw-rw- 1 root root 4, 64 2006-02-24 13:12 ttyS0
crw-rw-rw- 1 root root 1, 9 2006-02-24 13:12 urandom
crw-rw-rw- 1 root root 1, 5 2006-02-24 13:12 zero
舉例: mknod console c 5 1 這樣 crw-rw-rw- 1 root root 5, 1 2006-02-24 13:12 console
5。將編譯好的busybox拷貝到/bin下面,除了busybox外,所有其他的命令都是他的link
ash chgrp clear dd echo fgrep gzip ip ls modprobe mv ping pwd sed stty tar true zcat busybox chmod cp df egrep grep hostname kill mkdir more netstat ping2file rm sh sync tftp umount cat chown date dmesg false gunzip ifconfig ln mknod mount pidof ps rmdir sleep sysinfo touch uname
所有的命令你可以在busybox下面用make menuconfig來增減
6。同樣/sbin下面也是busybox的link
halt ifconfig init insmod klogd losetup lsmod mkswap modprobe reboot rmmod route swapoff swapon
7。同樣/usr/bin下面也是busybox的link
basename dirname env free id logger reset tail tr tty uptime which xargs
awk cut du expr head killall mkfifo sort test traceroute uniq wc whoami yes
上面幾乎是最全的link,各個看官可以酌情刪減,不過link也不佔什麼空間!
8。同樣/usr/sbin下面放著所有編譯完的可執行檔案,具體就不多說了
9。非常重要之/lib,務必重視
找到你編譯環境的target目錄,把需要的lib檔案先用strip壓縮(非target目錄下的,而已編譯環境提供的strip),先把最基本的libc, ld等等,必須同樣做跟target/lib裡面一樣的link。
然後根據特定的應用加相應的lib,不要把不用的加進去,lib比較佔空間。
10。在/etc下面加上需要的配置檔案,最最重要的是rcS
#!/bin/sh
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/sbin/scripts
UTC=yes
mount -n -t proc proc /proc
mount -n -t ramfs ramfs /tmp
mount -n -t devpts devpts /dev/pts
# build var directories
/bin/mkdir -m 0777 /tmp/var
/bin/mkdir -m 0777 /var/lock
/bin/mkdir -m 0777 /var/log
/bin/mkdir -m 0777 /var/run
/bin/mkdir -m 0777 /var/tmp
#/bin/mkdir -m 0777 /tmp/etc
#/bin/cp -a /usr/etc/* /etc
#/bin/cp -a /usr/dev/* /dev/
# loads the NPE ethernet modules into the kernel.
insmod /lib/modules/2.6.13.2/intel/ixp400.ko
# Firmware code for NPE Engine.
cat /etc/IxNpeMicrocode.dat > /dev/ixNpe
insmod /lib/modules/2.6.13.2/intel/ixp400_eth.ko netdev_max_backlog=500
insmod /lib/modules/led.ko
insmod /lib/modules/push_button.ko
下面的具體應用沒有再舉例加上了,這個是系統init必須的。
其他的情況類似如此了,我在附件裡面給了一個lunksys的GPL專案的target,大家看著比劃。
附件
四、生成一個ramdisk
#!/bin/sh
MODULE_NAME=ramdisk
RAMPATH=`pwd`
TMPPATH=${RAMPATH}/tmp
SOURCE=${RAMPATH}/../target
if [ ! -d ${TMPPATH} ]
then
mkdir ${TMPPATH}
fi
if [ `whoami` != 'root' ]
then {
echo "You should run the shell as root, Please rerun as a root."
echo "Aborting."
exit 1
}
fi
# Clear in tmp path
rm -rf ${TMPPATH}/tmpmnt
rm -rf ${TMPPATH}/ramrootfs
mkdir ${TMPPATH}/tmpmnt
# Clear the old ramdisk
rm -f ${RAMPATH}/$MODULE_NAME
# Make a temp file which size is suitable
dd if=/dev/zero of=${TMPPATH}/ramrootfs bs=1k count=6144
# Create a ext2 filesystem
mke2fs -F -m 0 -i 2000 ${TMPPATH}/ramrootfs
# Mount it to tmpmnt/
mount -o loop -t ext2 ${TMPPATH}/ramrootfs ${TMPPATH}/tmpmnt
# Copy everything from kernel to this.
cd ${TMPPATH}/tmpmnt
echo ${SOURCE}
cp -av ${SOURCE}/* .
cd ${TMPPATH}
# Unmount it the ext2 filesystem
umount ${TMPPATH}/tmpmnt
cat ${TMPPATH}/ramrootfs | gzip -9 > /${RAMPATH}/ramdisk
echo Copying ramdisk image to ${RAMPATH}
sync
這裡給出一個自動生成指令碼!
五、生成一個cramfs
找到cramfs的toolchain
。/mkcramfs -r $(FS1_DIR) $(FS_NAME).1
六、生成一個mksquashfs
找到squashfs的toolchain
。/mksquashfs $(FS_DIR) $(FS_NAME) -noappend -be -lzma -no-fragments -noI
做檔案系統最困難和最可能出問題的地方是在/lib庫和/dev方面,請大家多注意這兩方面
A directory structure contained within a disk drive or disk area. The total available disk space can be composed of one or more filesystems. A filesystem must be mounted before it can be accessed. To mount a filesystem, you must specify a directory to act as the mount point. Once mounted, any access to the mount point directory or its subdirectories will access the separate filesystem.
檔案系統是包括在一個磁碟(包括光碟、軟盤、閃盤及其它儲存裝置)或分割槽的目錄結構;一個可應用的磁碟裝置可以包含一個或多個檔案系統;如果您想進入一個檔案系統,首先您要做的是掛載(mount)檔案系統;為了掛載(mount)檔案系統,您必須指定一個掛載點。
* Linux 中,rootfs 是必不可少的。PC 上主要實現有 ramdisk 和直接掛載 HD(Harddisk,硬碟) 上的根檔案系統;嵌入式中一般不從 HD 啟動,而是從 Flash 啟動,最簡單的方法是將 rootfs load 到 RAM 的 RAMDisk,稍複雜的就是 直接從Flash 讀取的 Cramfs,更復雜的是在 Flash 上分割槽,並構建 JFFS2 等檔案系統。
* RAMDisk 將製作好的 rootfs 壓縮後寫入 Flash,啟動的時候由 Bootloader load 到RAM,解壓縮,然後掛載到 /。這種方法操作簡單,但是在 RAM 中的檔案系統不是壓縮的,因此需要佔用許多嵌入式系統中稀有資源 RAM。
ramdisk 就是用記憶體空間來模擬出硬碟分割槽,ramdisk通常使用磁碟檔案系統的壓縮存放在flash中,在系統初始化時,解壓縮到SDRAM並掛載根檔案系統, 在linux系統中,ramdisk有二種,一種就是可以格式化並載入,在linux核心2.0/2.2就已經支援,其不足之處是大小固定;另一種是 2.4的核心才支援,通過,ramfs來實現,他不能被格式化,但用起來方便,其大小隨所需要的空間增加或減少,是目前linux常用的ramdisk技術.
* initrd 是 RAMDisk 的格式,kernel 2.4 之前都是 image-initrd,Kernel 2.5 引入了 cpio-initrd,大大簡化了 Linux 的啟動過程,附合 Linux 的基本哲學:Keep it simple, stupid(KISS). 不過cpio-initrd 作為新的格式,還沒有經過廣泛測試,嵌入式 Linux 中主要採用的還是 image-initrd。
* Cramfs 是 Linus 寫的很簡單的檔案系統,有很好的壓縮綠,也可以直接從 Flash 上執行,不須 load 到 RAM 中,因此節約了 RAM。但是 Cramfs 是隻讀的,對於需要執行時修改的目錄(如: /etc, /var, /tmp)多有不便,因此,一般將這些目錄做成ramfs 等可寫的 fs。
* SquashFS 是對 Cramfs 的增強。突破了 Cramfs 的一些限制,在 Flash 和 RAM 的使用量方面也具有優勢。不過,據開發者介紹,在效能上可能不如 Cramfs。這也是一種新方法,在嵌入式系統採用之前,需要經過更多的測試
三、建一個包含所有檔案的目錄 ;
1。建一個目錄rootfs 用來裝檔案系統
2。mkdir bin dev etc lib proc sbin tmp usr var
3. ln -fs bin/busybox linuxrc(使用busybox)
4. 到系統 /dev 把所有的device打一個包,拷貝到 dev下面(最省事的做法);或者使用mknod來自己建所需要的device,我自己用的如下:
crw-rw-rw- 1 root root 5, 1 2006-02-24 13:12 console
crw-rw-rw- 1 root root 5, 64 2006-02-24 13:12 cua0
crw-rw-rw- 1 root root 63, 0 2006-02-24 13:12 dk0
crw-rw-rw- 1 root root 63, 1 2006-02-24 13:12 dk1
drwxr-xr-x 2 root root 4096 2006-02-24 13:12 flash
brw-rw-rw- 1 root root 3, 0 2006-02-24 13:12 hda
crw-rw-rw- 1 root root 36, 10 2006-02-24 13:12 ipsec
crw-rw-rw- 1 root root 241, 0 2006-02-24 13:12 ixNpe
crw-rw-rw- 1 root root 1, 2 2006-02-24 13:12 kmem
crw-rw-rw- 1 root root 126, 0 2006-02-24 13:12 ledman
lrwxrwxrwx 1 root root 16 2007-09-19 14:08 log -> /tmp/var/log/log
crw-rw-rw- 1 root root 1, 1 2006-02-24 13:12 mem
crw-rw-rw- 1 root root 90, 0 2006-02-24 13:12 mtd0
brw-rw-rw- 1 root root 31, 0 2006-02-24 13:12 mtdblock0
brw-rw-rw- 1 root root 31, 1 2006-02-24 13:12 mtdblock1
brw-rw-rw- 1 root root 31, 2 2006-02-24 13:12 mtdblock2
brw-rw-rw- 1 root root 31, 3 2006-02-24 13:12 mtdblock3
brw-rw-rw- 1 root root 31, 4 2006-02-24 13:12 mtdblock4
brw-rw-rw- 1 root root 31, 5 2006-02-24 13:12 mtdblock5
brw-rw-rw- 1 root root 31, 6 2006-02-24 13:12 mtdblock6
crw-rw-rw- 1 root root 90, 1 2006-02-24 13:12 mtdr0
crw-rw-rw- 1 root root 1, 3 2006-02-24 13:12 null
crw-rw-rw- 1 root root 108, 0 2006-02-24 13:12 ppp
crw-r--r-- 1 root root 5, 2 2006-03-29 15:56 ptmx
drwxr-xr-x 2 root root 4096 2006-03-29 15:56 pts
crw-rw-rw- 1 root root 2, 0 2006-02-24 13:12 ptyp0
brw-rw-rw- 1 root root 1, 0 2006-02-24 13:12 ram0
crw-rw-rw- 1 root root 1, 8 2006-02-24 13:12 random
crw-rw-rw- 1 root root 5, 0 2006-02-24 13:12 tty
crw-rw-rw- 1 root root 4, 0 2006-02-24 13:12 tty0
crw-rw-rw- 1 root root 3, 0 2006-02-24 13:12 ttyp0
crw-rw-rw- 1 root root 4, 64 2006-02-24 13:12 ttyS0
crw-rw-rw- 1 root root 1, 9 2006-02-24 13:12 urandom
crw-rw-rw- 1 root root 1, 5 2006-02-24 13:12 zero
舉例: mknod console c 5 1 這樣 crw-rw-rw- 1 root root 5, 1 2006-02-24 13:12 console
5。將編譯好的busybox拷貝到/bin下面,除了busybox外,所有其他的命令都是他的link
ash chgrp clear dd echo fgrep gzip ip ls modprobe mv ping pwd sed stty tar true zcat busybox chmod cp df egrep grep hostname kill mkdir more netstat ping2file rm sh sync tftp umount cat chown date dmesg false gunzip ifconfig ln mknod mount pidof ps rmdir sleep sysinfo touch uname
所有的命令你可以在busybox下面用make menuconfig來增減
6。同樣/sbin下面也是busybox的link
halt ifconfig init insmod klogd losetup lsmod mkswap modprobe reboot rmmod route swapoff swapon
7。同樣/usr/bin下面也是busybox的link
basename dirname env free id logger reset tail tr tty uptime which xargs
awk cut du expr head killall mkfifo sort test traceroute uniq wc whoami yes
上面幾乎是最全的link,各個看官可以酌情刪減,不過link也不佔什麼空間!
9。非常重要之/lib,務必重視
找到你編譯環境的target目錄,把需要的lib檔案先用strip壓縮(非target目錄下的,而已編譯環境提供的strip),先把最基本的libc, ld等等,必須同樣做跟target/lib裡面一樣的link。
然後根據特定的應用加相應的lib,不要把不用的加進去,lib比較佔空間。
10。在/etc下面加上需要的配置檔案,最最重要的是rcS
#!/bin/sh
export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/sbin/scripts
UTC=yes
mount -n -t proc proc /proc
mount -n -t ramfs ramfs /tmp
mount -n -t devpts devpts /dev/pts
# build var directories
/bin/mkdir -m 0777 /tmp/var
/bin/mkdir -m 0777 /var/lock
/bin/mkdir -m 0777 /var/log
/bin/mkdir -m 0777 /var/run
/bin/mkdir -m 0777 /var/tmp
#/bin/mkdir -m 0777 /tmp/etc
#/bin/cp -a /usr/etc/* /etc
#/bin/cp -a /usr/dev/* /dev/
# loads the NPE ethernet modules into the kernel.
insmod /lib/modules/2.6.13.2/intel/ixp400.ko
# Firmware code for NPE Engine.
cat /etc/IxNpeMicrocode.dat > /dev/ixNpe
insmod /lib/modules/2.6.13.2/intel/ixp400_eth.ko netdev_max_backlog=500
insmod /lib/modules/led.ko
insmod /lib/modules/push_button.ko
下面的具體應用沒有再舉例加上了,這個是系統init必須的。
其他的情況類似如此了,我在附件裡面給了一個lunksys的GPL專案的target,大家看著比劃。
四、生成一個ramdisk
#!/bin/sh
MODULE_NAME=ramdisk
RAMPATH=`pwd`
TMPPATH=${RAMPATH}/tmp
SOURCE=${RAMPATH}/../target
if [ ! -d ${TMPPATH} ]
then
mkdir ${TMPPATH}
fi
if [ `whoami` != 'root' ]
then {
echo "You should run the shell as root, Please rerun as a root."
echo "Aborting."
exit 1
}
fi
# Clear in tmp path
rm -rf ${TMPPATH}/tmpmnt
rm -rf ${TMPPATH}/ramrootfs
mkdir ${TMPPATH}/tmpmnt
# Clear the old ramdisk
rm -f ${RAMPATH}/$MODULE_NAME
# Make a temp file which size is suitable
dd if=/dev/zero of=${TMPPATH}/ramrootfs bs=1k count=6144
# Create a ext2 filesystem
mke2fs -F -m 0 -i 2000 ${TMPPATH}/ramrootfs
# Mount it to tmpmnt/
mount -o loop -t ext2 ${TMPPATH}/ramrootfs ${TMPPATH}/tmpmnt
# Copy everything from kernel to this.
cd ${TMPPATH}/tmpmnt
echo ${SOURCE}
cp -av ${SOURCE}/* .
cd ${TMPPATH}
# Unmount it the ext2 filesystem
umount ${TMPPATH}/tmpmnt
cat ${TMPPATH}/ramrootfs | gzip -9 > /${RAMPATH}/ramdisk
echo Copying ramdisk image to ${RAMPATH}
sync
這裡給出一個自動生成指令碼!
五、生成一個cramfs
找到cramfs的toolchain
。/mkcramfs -r $(FS1_DIR) $(FS_NAME).1
六、生成一個mksquashfs
找到squashfs的toolchain
。/mksquashfs $(FS_DIR) $(FS_NAME) -noappend -be -lzma -no-fragments -noI
做檔案系統最困難和最可能出問題的地方是在/lib庫和/dev方面,請大家多注意這兩方面