Linux:一步一步製作自己的根檔案系統
-
一步一步製作自己的根檔案系統
在這裡,實驗過程使用的是九鼎提供的S5PV210開發板,實驗核心同樣來自其官方資料盤中Linux資料包中的的QT4.8中的相關原始碼,實驗的NFS檔案系統在虛擬中的Ubuntu14.04中建立.
-
建立檔案系統根目錄
rootfs有2種提現形式:nfs方式啟動的資料夾形式和用來燒錄的映象形式,當然這裡指的是前者.
開幹了,隨便找個位置新建一個新的資料夾作為NFS檔案系統的根目錄,這裡我建立的資料夾的絕對路徑是"/root/s5pv210-qt/s5pv210_qt4.8/rootfs-self/:
如果需要開發板進行NFS掛載的朋友,記得將新建的目錄匯出到NFS伺服器上,否則這個資料夾是不支援NFS的方式掛載的,相關NFS伺服器的搭建請自行百度,或者參考我的相關部落格,在這裡我是通過開發板掛載自制的這個NFS來驗證的.
這個時候從開發版掛載這個檔案系統並啟動時,會失敗,提示如下:
[ 24.157685] VFS: Mounted root (nfs filesystem) on device 0:12. [ 24.162105] Freeing init memory: 208K [ 24.168151] Failed to execute /linuxrc. Attempting defaults... [ 24.180174] Kernel panic - not syncing: No init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
意思是NFS掛載成功了,但是啟動/linuxrc失敗了,這說明我們根目錄下需要這個/linuxrc,不難猜測這應該是在系統啟動後第一個從檔案系統執行的程式了,我們目前自制的根目錄下是空的,這當然不行,我也試了在根目錄下給它建立一個該檔案,結果仍然也是失敗的,這裡不做過多研究,但是我猜測這個跟我們在開發版中uboot的啟動引數中設定的內容有關,在我的另外一篇部落格中,設定開發板載入NFS檔案系統的相關步驟中,就有給uboot設定了一個這個引數"init=/linuxrc",所以我覺得應該是這裡指定的啟動程式是誰,有興趣的朋友請自己嘗試.
那麼既然缺少這個程式,我們就得想辦法給他安放一個,這裡可以選擇安裝busybox.
-
安裝"/linuxrc"(這裡是busybox)
busybox是一個開源專案,所以原始碼可以直接從官網等網站下載,busybox的版本差異不大,這裡用的是busybox-1.19.2.tar.gz,解壓後進入busybox-1.19.2目錄下,因為我們編譯後是跑在開發板上的,所以這裡要進行交叉編譯工具的確認或修改,首先修改Makefile,確認下面兩個變數的值設定滿足要求,我這邊的是:
ARCH = arm
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
使用"make menuconfig"命令修改並生成新的檔案,相關配置參考如下:
Busybox Settings --->
Build Options --->
[*] Build BusyBox as a static binary(no shared libs)
Busybox Settings --->
Busybox Library Tuning--->
[*] vi-style line editing commands
[*] Fancy shell prompts
Linux Module Utilities --->
[ ] Simplified modutils
[*] insmod
[*] rmmod
[*] lsmod
[*] modprobe
[*] depmod
Linux System Utilities --->
[*] mdev
[*] Support /etc/mdev.conf
[*] Support subdirs/symlinks
[*] Support regular expressions substitutions when renaming dev
[*] Support command execution at device addition/removal
[*] Support loading of firmwares
繼續修改配置檔案,設定busybox的安裝路徑為我們要製作的NFS檔案系統的根目錄,譬如我的路徑是"/root/s5pv210-qt/s5pv210_qt4.8/rootfs-self/",設定的地方在:
Busybox Settings --->
Installation Options ("make install" behavior) --->
(./_install) BusyBox installation prefix
如上所示,預設的安裝路徑會是當前busybox原始碼所在路徑的_install下.設定完成後執行"make"及"make install"命令即可.
這個時候我們的NFS根檔案裡面不是空無一物了,有linuxrc等一些東西,接下來我們繼續開啟開發板掛載這個NFS檔案系統,看看如何:
[ 27.219456] VFS: Mounted root (nfs filesystem) on device 0:12.
[ 27.223865] Freeing init memory: 208K
can't run '/etc/init.d/rcS': No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
可以看到,沒有了之前的錯誤,也不會核心崩潰,但是會提示一些檔案找不到,比如"/etc/init.d/rcS"和一些tty的裝置檔案,這個時候我們敲擊回車,可以發現命令列已經出來了,這說明我們能夠跑起來了,只是還不夠完美,有一些問題需要解決,我們一步一步來.
-
建立"/etc/init.d/rcS"檔案
既然說找不到"/etc/init.d/rcS"這個檔案,那麼我們就建立一個這個檔案,可以在網上檢視一些資料學習一下這個檔案,不難了解到這個檔案是一個啟動指令碼,有興趣的朋友可以檢視自己的ubuntu主機中的該檔案和其他資料進行學習,算是比較簡單的一個指令碼,這裡直接貼出內容,並在後續分析一些現象時對相關內容做一些歸納:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
/bin/hostname -F /etc/sysconfig/HOSTNAME
ifconfig eth0 192.168.1.88
建立完成後記得修改這個檔案的許可權,否則開發板開機後提示無該檔案的執行許可權,一般是給個執行許可權就夠了,不過這裡我沒有試,我是直接給的所有許可權,執行命令"chmod 0777 /root/s5pv210-qt/s5pv210_qt4.8/rootfs-self/etc/init.d/rcS"後重啟開發板,看看現在啟動這個NFS後的情況會怎樣:
[ 23.169821] VFS: Mounted root (nfs filesystem) on device 0:12.
[ 23.174233] Freeing init memory: 208K
mount: can't read '/etc/fstab': No such file or directory
/etc/init.d/rcS: line 8: can't create /proc/sys/kernel/hotplug: nonexistent directory
mdev: chdir(/dev): No such file or directory
hostname: can't open '/etc/sysconfig/HOSTNAME': No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
OK,有一個mount命令的錯誤,等等,說明我們要一一解決這些錯誤,並且這些錯誤都是由我們上面建立的這個指令碼在執行過程中引出來的.
-
建立"/etc/fstab"檔案
"/etc/fstab"檔案其實就是我們執行"mount -a"時所去載入的配置檔案,他會按照該配置檔案執行掛載操作.
# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /var tmpfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
關於這個檔案的細節有興趣的朋友自行百度學習,這裡只做簡單瞭解,不難看出我們配置檔案的意思就是我們會掛載一些檔案系統,掛載點是在配置檔案中定義的對應目錄,譬如這裡的prop檔案系統會掛載在"/proc"下,可想而知,我們當前製作的檔案系統中沒有這些目錄,如果只建立了這個檔案,等檔案系統被掛在後,肯定會提示找不到對應掛載點的一些錯誤,那麼是不是這樣呢,我們儲存這個配置檔案後,重啟開發板看看:
[ 23.184087] VFS: Mounted root (nfs filesystem) on device 0:12.
[ 23.188501] Freeing init memory: 208K
mount: mounting proc on /proc failed: No such file or directory
mount: mounting sysfs on /sys failed: No such file or directory
mount: mounting tmpfs on /var failed: No such file or directory
mount: mounting tmpfs on /tmp failed: No such file or directory
mount: mounting tmpfs on /dev failed: No such file or directory
/etc/init.d/rcS: line 8: can't create /proc/sys/kernel/hotplug: nonexistent directory
mdev: chdir(/dev): No such file or directory
hostname: can't open '/etc/sysconfig/HOSTNAME': No such file or directory
can't open /dev/tty2: No such file or directory
can't open /dev/tty3: No such file or directory
can't open /dev/tty4: No such file or directory
果然,如我們猜想一樣,那麼解決這些mounting就非常簡單了,原因已知,解決它就是建立這些對用的掛載點目錄,之後重啟開發板再看看:
[ 24.194705] VFS: Mounted root (nfs filesystem) on device 0:12.
[ 24.199113] Freeing init memory: 208K
hostname: can't open '/etc/sysconfig/HOSTNAME': No such file or directory
誒,神奇的發現不僅mounting失敗的訊息沒有了,後面很多錯誤也沒有了,其實仔細一看就能發現,其他的錯誤是對應的掛載點中的檔案或者目錄找不到的錯誤,這說明我們掛載了這些檔案系統後,這些工作的檔案系統就正常了.
在這裡,不得不對"/etc/init.d/rcS"中的mdev的作用進行歸納,指令碼中其他的命令都很簡單理解.
mdev是udev的嵌入式簡化版本,udev/mdev是用來配合linux驅動工作的一個應用層的軟體,udev/mdev的工作就是配合linux驅動生成相應的/dev目錄下的裝置檔案這裡我們只是通過一些直觀的現象來初步理解udev/mdev的工作效果.在rcS檔案中沒有啟動mdev的時候,/dev目錄下啟動後是空的;在rcS檔案中新增上mdev有關的2行配置項後,再次啟動系統後發現/dev目錄下生成了很多的裝置驅動檔案。
那麼其實到這一步,基於嵌入式這種小型的檔案系統可以說是完成了,但是不夠完美,很多功能有缺陷,為什麼呢?我們可以參考我們ubuntu主機中的檔案系統,發現他有很多的配置檔案,當然我們沒必要做的那麼龐大,沒有意義,但是我們可以儘量完美一些,有興趣的朋友還可以去分析busybox原始碼,這裡不做分析了,沒記錯的話busybox首先將試圖解析"/etc/inittab"來獲取進一步的初始化配置資訊,可以參考busybox原始碼init/init.c中的parse_inittab()函式,而事實上,一些檔案系統中並沒有"/etc/inittab"這個配置檔案,而之前卻先看到了找不到"etc/init.d/rcS"檔案的錯誤而不是找不到"/etc/inittab"檔案,這些答案都能通過分析busybox原始碼得到,這裡給出答案,其實busybox試圖解析"/etc/inittab"失敗後並不會報錯,而會繼續使用預設定義的初始化指令碼,也就是原始碼中"INIT_SCRIPT"巨集所定義的值,這個巨集的預設值是"etc/init.d/rcS",再比如我們不在這個指令碼中設定PATH環境變數,卻仍能有PATH環境變數的一些功效(諸如使用"ls"命令等),這其實也是busybox中硬編碼幫我們設定了這些環境變數的.
-
建立"/etc/inittab"檔案