對於root fileSystem的官方描述為FHS(FileSystem hierachy Stardard)。在根目錄下的最進階目錄都有明確的目的,然而很多是作為多使用者系統的,而嵌入式系統對這些規則的遵循可以比較鬆動。
根目錄系統
/bin |
Essential user command binaries |
/boot |
Static files used by the bootloader --》根據我們的bootloader以及他的配置,可能可以刪除。這取決於我們的bootloader是否可以在kernel啟動之前從根檔案系統中獲得kernel的image。 |
/dev |
Devices and other special files |
/etc |
System configuration files, including startup files |
/home |
User home directories -》用於擴充的使用者環境,可刪除 |
/lib |
Essential libraries, such as the C library, and kernel modules |
/media |
Mount points for removable media |
/mnt |
Mount points for temporarily mounted filesystems -》用於擴充的使用者環境,可刪除 |
/opt |
Add-on software packages -》用於擴充的使用者環境,可刪除 |
/proc |
Virtual filesystem for kernel and process information |
/root |
Root user's home directory -》用於擴充的使用者環境,可刪除 |
/sbin |
Essential system administration binaries |
/sys |
Virtual filesystem for system information and control (buses, devices, and drivers) |
/tmp |
Temporary files,chmod 1777 tmp,這是確保由建立的使用者來進行刪除。 |
/usr |
Secondary hierarchy containing most applications and documents useful to most users, including the X server。在裡面建立bin,sbin,lib三個子目錄。其他的字目錄例如man、src、local都可能無需在嵌入式OS中使用。 |
/var |
Variable data stored by daemons and utilities,建立lib, lock, log, run, tmp,使用chmod 1777 tmp |
我們可以字啊$PRJROOT下面建立rootfs ,在裡面建立上面的檔案系統。甚至可以更狠地刪除/tmp和/var,但是可以會危害到其他的操作,不建議這樣處理。這種刪除的處理只是基於是否有用的考慮,不會對size有什麼影響。可以更狠地刪除/proc和/sys如果不需要虛擬檔案系統,但是一些基本的命令,例如ps,mount,ifconfig,modprobe需要使用 /proc,而更多的應用也需要使用/sys,除非我們限定嵌入式系統非常有限的使用範圍,否則不要這樣處理。
lib庫檔案
/bin /sbin /usr/bin /usr/sbin的區別。/bin用於儲存使用者和系統管理員的基本(或者基礎)二進位檔案,/sbin用於儲存系統管理員所需,但是一般使用者不需要的二進位檔案,/usr/bin 和/usr/sbin的差異類似,他們儲存的不是基本二進位檔案。在/lib中儲存用於系統啟動和應用於基本命令,而/usr/lib則儲存其他的 lib,例如perl5在/usr/lib/perl5中有lib。
lib有四種格式:
- libLIBRARY_NAME-GLIBC_VERSION.so,例如libc-2.9.so,libcidn-2.9.so
- libLIBRARY_NAME.so.MAJOR_REVISION_VERSION,例如libc.so.6 -> libc-2.9.so,libcidn.so.1 -> libcidn-2.9.so
- libLIBRARY_NAME.so,例如libcidn.so -> libcidn.so.1
- 靜態庫:libLIBRARY_NAME.a,例如libc.a,libcrypt.a
-rwxr-xr-x 1 wei wei 105210 05-15 16:09 libcrypt-2.9.so
-rw-r--r-- 1 wei wei 139684 05-15 16:09 libcrypt.a
lrwxrwxrwx 1 wei wei 13 05-15 16:09 libcrypt.so -> libcrypt.so.1
lrwxrwxrwx 1 wei wei 15 05-15 16:09 libcrypt.so.1 -> libcrypt-2.9.so
對比這些命名方式,glibc的庫比較特別,它動態連結程式庫ld的格式為ld-GLIBC_VERSION.so,ld- linux.so.MARHOR_REVISION_VERSION(ARM,i386,m68k)或者 ld.so.MAJOR_REVISION_VERSION(MIPS,PowerPC)。這不是一個真正的庫,ld.so是ELF二進位loader觸發用來將動態連結程式庫載入到應用程式的存貯空間中。
在嵌入式作業系統中,我們如果想在host查看應用使用了哪些動態連結程式庫,需要使用 cross-platform的readelf來替代ldd,例如powerpc-linux-readelf。
對於target的檔案系統,需要將相關(所需)的lib拷貝至rootfs/lib中。需要libLIBRARY_NAME-GLIBC_VERSION.so和libLIBRARY_NAME.so.MAJOR_REVISION_VERSION。檔案系統的建立包括:lib、kernel modules,kernel Images
#將全部的lib檔案copy到我們的target的lib中,當然我們也可以只選取我們需要的部分
cd ${TARGET_PREFIX}/lib
cp *-*.so ${PRJROOT}/rootfs/lib
cp -d *.so.[*0-9] ${PRJROOT}/rootfs/lib
cp libSegFault.so libmemusage.so libpcprofile.so ${PRJROOT}/rootfs/lib
#如果我們不需要所有的lib,選擇其中的某些有用的部分,我們可以如下進行操作
cd ${TARGET_PREFIX}/lib
for file in libc libcrypt libdl libm libpthread libresolv libutil
do
cp $file-*.so ${PRJROOT}/rootfs/lib
cp -d $file.so.[*0-9] ${PRJROOT}/rootfs/lib
done
cp -d ld*.so* ${PRJROOT}/rootfs/lib
#如果我們選擇了libnss_*.so,其中libnss_file和libnss_dns常用,需要將nsswitch.conf檔案放置在/etc中,並根據需要進行配置。
cp ${PRJROOT}/build-tools/src-glibc/glibc-20081113T2206/nss/nsswitch.conf ${PRJROOT}/rootfs/etc
#lib檔案是比較大的,可以採用strip進行裁剪,如下,原來的大小為12.488M,整理後為2.812M,空間大大地減少了。當然如果我們對空間大小不敏感,現在的存貯容量也越來越大,我們也可以不進行此步驟。
i586-linux-strip ${PRJROOT}/rootfs/lib/*.so
#copy核心模組,並在etc/下增加modprobe.conf檔案(用於給出模組的參數,步驟不太詳細,可能echo > ${PRJROOT}/rootfs/etc/modprobe.conf就可以了)。
cp -a ${PRJROOT}/images/myproject/modules-2.6.29-menlow/* ${PRJROOT}/rootfs
echo > ${PRJROOT}/rootfs/etc/modprobe.conf
#copy 相關的kernel image
mkdir ${PRJROOT}/rootfs/boot
cp ${PRJROOT}/images/myproject/bzImage-2.6.29-menlow ${PRJROOT}/rootfs/boot/vmlinuz--2.6.29-menlow
cp ${PRJROOT}/images/myproject/System.map-2.6.29-menlow ${PRJROOT}/rootfs/boot/
cp ${PRJROOT}/images/myproject/2.6.29-menlow.config ${PRJROOT}/rootfs/boot/config-2.6.29-menlow
裝置檔案
乙太網路是不作為裝置檔案,這點比較特殊。靜態裝置檔案指只需要建立一次。
[wei@wei rootfs]$ ls /dev/ttyS1* -l
crw-rw---- 1 root uucp 4, 65 05-31 08:55 /dev/ttyS1
第一字母表示類型,c表示character,b表示block,後面的4是major號碼,65是minor號碼,這是核心用於需要驅動管理的依賴。
建立靜態裝置檔案:
cd ${PRJROOT}/rootfs/dev
[wei@wei dev]$ su -m
?ü??£o
[root@wei dev]# mknod -m 600 mem c 1 1
[root@wei dev]# mknod -m 666 null c 1 3
[root@wei dev]# mknod -m 666 zero c 1 5
[root@wei dev]# mknod -m 644 random c 1 8
[root@wei dev]# mknod -m 600 tty0 c 4 0
[root@wei dev]# mknod -m 600 tty1 c 4 1
[root@wei dev]# mknod -m 600 ttyS0 c 4 64
[root@wei dev]# mknod -m 666 tty c 5 0
[root@wei dev]# mknod -m 600 consol c 5 1
[root@wei dev]# chmod 644 random
[root@wei dev]# chmod 600 tty0 tty1 ttyS0
[wei@wei dev]$ ln -s /proc/self/fd fd
[wei@wei dev]$ ln -s fd/0 stdin
[wei@wei dev]$ ln -s fd/1 stdout
[wei@wei dev]$ ln -s fd/2 stderr
在幾年前linux2.4的版本中,在/dev中有1萬8千個裝置檔案,但是在2.6的版本中,通過動態裝置檔案的方式大大地減少了。靜態裝置檔案的一個問題,就是我們無法通過查看/dev檔案來確定這個裝置是否真實存在或者有效,由此引入動態裝置檔案系統,在/dev中的只有可以使用的裝置。在 linux2.6中,通過udev來實現,它將裝置mount在/sys,使得裝置、驅動等資訊可以在user space中,他克服了熱插指令碼/sbin/hotplug甚多不足,並最終取代了它。
需要安裝udev
[wei@wei udev-142]$ ./autogen.sh
[wei@wei udev-142]$ make CROSS_COMPILE=i586-linux- DESTDIR=${PRJROOT}/rootfs install
在rootfs/lib/udev/, rootfs/etc/udev/, rootfs/etc/scsi_id.config
udev 等待當裝置插入或者卸載時來自核心的uevents,根據訊息內容或者在/sys中的裝置資訊在udev的rules中尋找匹配,如果找到,就產生或者刪除裝置檔案,執行驅動的載入或者卸載,或者提醒使用者空間的程式。這些資訊是通過netlink socket來傳遞的。
Busybox
在linux中有大量Unix的的命令,我們不能期待通過交叉編譯分別將他們編譯出來,我們可以藉助一些系統的app,例如busybox。在moblin中如果編譯busybox,需要下載ncurses-devel
busybox和kernel在配置一樣相似,如果使用預設,可以用defconfig,也可以使用menuconfig來進行配置。
Busybox settings --->
Build option --->
[*] Build BusyBox as a static binary (no shared libs) 這是對於小的系統Busybox以及小部分的lib,不需要整個C庫,使得系統更為簡單的和小巧。我想在moblin中並不需要這樣處理。
Linux System Utilities ---> (查過,下面這個屬於預設開啟)
[*] mdev
[*] Support /etc/mdev.conf
[ ] Support command execution at device addition/removal
必須選擇 mdev 選項, 否則不能啟用udev。
執行 make install進行編譯,編譯完後,會出現_install目錄,包含bin、sbin、usr三個目錄和一個linuxrc檔案。
$ make ARC=x86 CROSS_COMPILE=i586-linux- CONFIG_PREFIX=${PRJROOT}/rootfs install
Busybox是一個工具的整合,將ls,ps,等等命令連結指向busybox,busybox可提供這些工具的功能。無需我們分別來編譯這些工具集合。
[wei@wei bin]$ pwd
/home/wei/workspace/mywork/moblin/rootfs/bin
[wei@wei bin]$ ls -l
?? 1460
lrwxrwxrwx 1 wei wei 7 06-03 11:48 addgroup -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 adduser -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 ash -> busybox
-rwxr-xr-x 1 wei wei 1490596 06-03 11:48 busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 cat -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 catv -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 chattr -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 chgrp -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 chmod -> busybox
lrwxrwxrwx 1 wei wei 7 06-03 11:48 chown -> busybox
同樣在sbin/,usr/bin ,usr/sbin中的命令也指向該 busybox
我們在etc/profile
[wei@wei rootfs]$ cd etc
[wei@wei etc]$ cat profile
#Set Path
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
#set other libary path 這裡填寫非lib/的其他庫的位置。
#LD_LIBRARY_PATH=
#export LD_LIBRARY_PATH
系統啟動
主要有System V init和busybox兩種方式。moblin使用system V init的方式,我們分別對它以及busybox作為系統啟動進行嘗試:
原始的sysvinit 2.86,這個也可以在ftp://ftp.cistron.nl/pub/people/miquels/sysvinit中下載,可以看到這個自2004之後就沒有再更新,可能已經相當之成熟。
$ cd ${PRJROOT}/sysapps/sysvinit-2.86/src
$ make CC=i586-linux-gcc
$ make BIN_OWNER="$(id -un)" BIN_GROUP="$(id -gn)" ROOT=${PRJROOT}/rootfs install
可以將原來指向busybox的bootlogd, halt, init, killall5, last, mesg, mountpoint, pidof, poweroff, reboot, runlevel, shutdown, suloing, telinit, utmpdmp, wall更新為sysvinit的編譯結果。我們不使用root許可權來進行編譯所以需要指定使用者和所在使用者組。由於嵌入式作業系統一般都不是多使用者系統,所以對使用者權限設定不敏感。如果我們需要多使用者的方式,可以使用root許可權,但是需要非常小心,任何在root許可權下面的操作都是需要謹慎。我們也可以用普通使用者編譯,然手在rootfs中修改這些命令的許可權。
Busybox在example裡面有inittab,我們可以將它copy我們的rootfs/etc目錄下面。根據initab中:
::sysinit:/etc/init.d/rcS
我們在etc/下面建立了init.d目錄,以及rcS檔案,rcS檔案,我們給出:
#!/bin/sh
# Set Path
PATH=/bin:/sbin:/usr/bin:/usr/sbin
# Remount the root filesystem in read-write (requires /etc/fstab)
mount -n -o remount,rw /
# Mount /proc filesystem
mount /proc
# Start the network interface
#/sbin/ifconfig eth0 192.168.1.2