製作linux文件系統
① 如何製作 linux 文件系統
一、什麼是文件系統 (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
[NextPage]
7、同樣/usr/bin下面也是busybox的link
basename dirname env free id logger reset tail tr tty uptime which xargs
awk cut 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 moles into the kernel. insmod /lib/moles/2.6.13.2/intel/ixp400.ko # Firmware code for NPE Engine. cat /etc/IxNpeMicrocode.dat > /dev/ixNpe insmod /lib/moles/2.6.13.2/intel/ixp400_eth.ko netdev_max_backlog=500 insmod /lib/moles/led.ko insmod /lib/moles/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方面,請大家多注意這兩方面。
② Linux的文件系統
Linux的文件類型分為普通文件、d目錄文件、b塊設備文件、c字元設備文件(串口設備)、s套接字文件(特殊文件scoket)、l鏈接文件。
例如下圖,d開頭的是目錄文件,-開頭的是普通文件,l開頭的是鏈接文件
以touch,cp,tar,echo,cat等工具命令創建的文件都是普通文件,普通文件又分為以下三種:
1)純文本文件:文件內容可以直接讀取到數據(ASCL text)
2)二進制文件:linux中可執行文件(命令)
3)數據格式文件(一種特殊的文件 data)
ls -ld可以顯示所有的目錄文件
linux系統中的鏈接文件與WIN系統的快捷方式基本差不多,linux中鏈接文件又分為硬鏈接與軟鏈接。
硬鏈接: 是指通過索引節點來進行鏈接,在系統中多個文件各指向同一個索引節點,是可以的正常允許的,這種情況下的文件被稱之為硬鏈接。實際生產環境中用戶可以通過硬鏈接的方式來防止誤刪重要數據。
ln 源文件名 鏈接文件名 創建硬鏈接文件
軟鏈接: 也稱符號鏈接(快捷方式),實際上它是一個文本文件,它存儲著指向源文件鏈接的位置信息。
ln -s 源文件名 鏈接文件名 創建軟鏈接文件
另外要注意目錄是不可以創建硬鏈接文件的,但可創建軟鏈接文件,如下圖:
關於文件的軟鏈接和硬鏈接,總結起來有以下四種情況:
1)刪除源文件時,硬鏈接文件正常使用,軟鏈接文件就失效了。
2)刪除硬鏈接時,對源文件與軟鏈接無影響。
3)刪除軟鏈接時,對源文件與硬鏈接無任何影響。
4)刪除源文件、硬鏈接文件後,整個文件就會被刪除。
對於目錄的軟鏈接和硬鏈接,總結如下:
1)目錄是不可創建硬鏈接文件,可以創建軟鏈接文件。
2)目錄的軟鏈接是生產環境中非常實用的。
3)所有目錄都有一個硬鏈接「.」,目錄硬鏈接是不可跨越文件系統的。
Linux文件的擴展名主要是為了方便區分不同的文件,和windows的強類型擴展名不一樣。
1、.tar .tar.gz .tgz .zip 這類表示壓縮文件
2、.sh 表示shell腳本文件
3、.html .php .jsp 網頁文件
4、.conf 系統服務的配置文件
5、.rpm 表示RPM安裝包文件
每一個文件都有自己的屬性信息,它的屬性信息包括:索引節點、文件類型、許可權信息、所有者、所屬組、最近修改時間、大小、文件名或目錄名、硬鏈接數量。
我們以下圖的cron.daily這個文件為例,d表示文件類型是目錄文件,rwxr-xr-x這個表示許可權,第一個rwx表示的文件所有者用戶的許可權,第二個r-x表示的是所屬組的許可權,第三個r-x表示的是其他用戶的許可權。2表示硬鏈接數量,第一個root表示文件所有者是root,第二個root表示所屬組,42表示文件大小,May 27 2021表示最後的修改時間,corn.daily是文件名稱。
其中的索引節點編號需要通過ls -i才能看到,在最左邊顯示的那一串數字,如下圖所示:
③ linux內核編譯和根文件系統製作過程
內核編譯:
make
menuconfig配置相應的平台,然後保存退出直接make命令就可以編譯了。
文件系統製作:
一般都用busybox開源軟體來做,下載,解壓,然後make
menuconfig配置你想要的屬性,然後保存退出,make就可以了,然後make
install就會在目錄下看到__install的目錄就是你要的根文件系統目錄了。
④ 如何製作Linux根文件系統
根文件系統一直以來都是所有類Unix操作系統的一個重要組成部分,也可以認為是嵌入式Linux系統區別於其他一些傳統嵌入式操作系統的重要特徵,它給Linux帶來了許多強大和靈活的功能,同時也帶來了一些復雜性。我們需要清楚的了解根文件系統的基本結構,以及細心的選擇所需要的系統庫、內核模塊和應用程序等,並配置好各種初始化腳本文件,以及選擇合適的文件系統類型並把它放到實際的存儲設備的合適位置。
Linux的根文件系統以樹型結構組織,包含內核和系統管理所需要的各種文件和程序,一般說來根目錄」/」下的頂層目錄都有一些比較固定命名和用途。
下面列出了一個Linux根文件系統中的比較常見的目錄結構:
/bin 存放二進制可執行命令的目錄
該目錄下存放所有用戶都可以使用的、基本的命令,這些命令在掛接其它文件系統之前就可以使用,所以/bin目錄必須和根文件系統在同一個分區中。
/bin目錄下常用的命令有:cat,chgrp,chmod,cp,ls,sh,kill,mount,umount,mkdir,m knod,[,test等「[」命令其實就是test命令,我們在利用Busybox製作根文件系統時,在生成的bin目錄下,可以看到一些可執行的文件,也就是可用的一些命令。
/dev 存放設備文件的目錄
該目錄下存放的是設備文件,設備文件是Linux中特有的文件類型,在Linux系統下,以文件的方式訪問各種設備,即通過讀寫某個設備文件操作某個具體硬體。比如通過"dev/ttySAC0"文件可以操作串口0,通過"/dev/mtdblock1"可以訪問MTD設備的第2個分區。
/etc 存放系統管理和配置文件的目錄
該目錄下存放著各種配置文件,對於PC上的Linux系統,/etc目錄下的文件和目錄非常多,這些目錄文件是可選的,它們依賴於系統中所擁有的應用程序,依賴於這些程序是否需要配置文件。在嵌入式系統中,這些內容可以大為精減。
/home 用戶主目錄,比如用戶user的主目錄就是/home/user,可以用~user表示
用戶目錄,它是可選的,對於每個普通用戶,在/home目錄下都有一個以用戶名命名的子目錄,裡面存放用戶相關的配置文件。
/lib 存放動態鏈接共享庫的目錄
該目錄下存放共享庫和可載入(驅動程序),共享庫用於啟動系統。運行根文件系統中的可執行程序,比如:/bin /sbin 目錄下的程序。
/sbin存放系統管理員使用的管理程序的目錄
該目錄下存放系統命令,即只有管理員能夠使用的命令,系統命令還可以存放在/usr/sbin,/usr/local/sbin目錄下,/sbin目錄中存放的是基 本的系統命令,它們用於啟動系統,修復系統等,與/bin目錄相似,在掛接其他文件系統之前就可以使用/sbin,所以/sbin目錄必須和根文件系統在同一個分區中。
/sbin目錄下常用的命令有:shutdown reboot fdisk fsck等,本地用戶自己安裝的系統命令放在/usr/local/sbin目錄下。
/tmp 公用的臨時文件存儲點
用於存放臨時文件,通常是空目錄,一些需要生成臨時文件的程序用到的/tmp目錄下,所以/tmp目錄必須存在並可以訪問。
/root 系統管理員的主目錄
根用戶的目錄,與此對應,普通用戶的目錄是/home下的某個子目錄。
/mnt 系統提供這個目錄是讓用戶臨時掛載其他的文件系統。
用於臨時掛載某個文件系統的掛接點,通常是空目錄,也可以在裡面創建一引起空的子目錄,比如/mnt/cdram /mnt/hda1 。用來臨時掛載光碟、硬碟。
/proc 虛擬文件系統,可直接訪問這個目錄來獲取系統信息。
這是一個空目錄,常作為proc文件系統的掛接點,proc文件系統是個虛擬的文件系統,它沒有實際的存儲設備,裡面的目錄,文件都是由內核臨時生成的,用來表示系統的運行狀態,也可以操作其中的文件控制系統。
/usr 最龐大的目錄,要用到的應用程序和文件幾乎都在這個目錄。
/usr目錄的內容可以存在另一個分區中,在系統啟動後再掛接到根文件系統中的/usr目錄下。裡面存放的是共享、只讀的程序和數據,這表明/usr目錄下的內容可以在多個主機間共享,這些主要也符合FHS標準的。/usr中的文件應該是只讀的,其他主機相關的,可變的文件應該保存在其他目錄下,比如/var。/usr目錄在嵌入式中可以精減。
/var 某些大文件的溢出區
與/usr目錄相反,/var目錄中存放可變的數據,比如spool目錄(mail,news),log文件,臨時文件。
---------------------------------------------------------------------
一、移植環境:
1、 Ubuntu 10.10發行版
2、 u-boot.bin
3、 目標機:FS_S5PC100平台
4、 交叉編譯器 arm-cortex_a8-linux-gnueabi-gcc
---------------------------------------------------------------------
二、移植步驟
1、 源碼下載
我們選擇的版本是busybox-1.17.3.tar.bz2下載路徑為:
http://busybox.net/downloads/
2、 解壓源碼
$ tar xvf busybox-1.17.3.tar.bz2
3、 進入源碼目錄
$ cd busybox-1.17.3
4、 配置源碼
$ 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)
(arm-cortex_a8-linux-gnueabi-) Cross Compiler prefix
() Additional CFLAGS
5、 編譯
$ make
6、 安裝
busybox默認安裝路徑為源碼目錄下的_install
$ make install
7、 進入安裝目錄下
$ cd _install
$ ls
bin linuxrc sbin usr
8、 創建其他需要的目錄
$ mkdir dev etc mnt proc var tmp sys root
9、 添加庫
在_install目錄下創建一個lib文件夾,將工具鏈中的庫拷貝到lib目錄下
$ mkdir lib
$ cp /home/linux/x-tools/arm-cortex_a8-linux-gnueabi/arm-cortex_a8-linux-gnueabi/lib/* ./lib/
刪除lib下的所有目錄、.o文件和.a文件,對庫進行瘦身以減小文件系統的大小
$ rm *.o *.a
$ arm-cortex_a8-linux-gnueabi-strip lib/*
10、 添加系統啟動文件
在etc下添加文件inittab
$ vim /etc/inittab
文件內容如下:
#this is run first except when booting in single-user mode.
:: sysinit:/etc/init.d/rcS
# /bin/sh invocations on selected ttys
# Start an "askfirst" shell on the console (whatever that may be)
::askfirst:-/bin/sh
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
在etc下添加文件fstab
$ vim /etc/fstab
文件內容如下:
#device mount-point type options mp fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
這里我們掛在的文件系統有三個proc、sysfs和tmpfs,在內核中proc和sysfs默認都支持,而tmpfs是沒有支持的,我們需要添加tmpfs的支持
修改內核配置:
$ make menuconfigFile systems --->
Pseudo filesystems --->
[*] Virtual memory file system support (former shm fs)
[*] Tmpfs POSIX Access Control Lists
重新編譯內核
$ make zImage
在etc下創建init.d目錄,並在init.d下創建rcS文件
$ mkdir /etc/init.d -p
$ vim /etc/init.d/rcS
rcS文件內容為:
#!/bin/sh
# This is the first script called by init process
/bin/mount -a
為rcS添加可執行許可權:
$ chmod +x init.d/rcS
在etc下添加profile文件
$ vim /etc/profile
文件內容為:
#!/bin/sh
export HOSTNAME=farsight
export USER=root
export HOME=root
#export PS1="\[\u@\h \W\]\$ "
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
11、 設備文件創建
根文件系統中有一個設備節點是必須的,在dev下創建console節點
$ mknod dev/console c 5 1
重要:新製作的文件系統尺寸若超出8M,刪除不需要的庫文件。