对于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,除非我们限定嵌入式系统非常有限的使用范围,否则不要这样处理。
/bin /sbin /usr/bin /usr/sbin的区别。/bin用于保存用户和系统管理员的基本(或者基础)二进制文件,/sbin用于保存系统管理员所需,但是一般用户不需要的二进制文件,/usr/bin 和/usr/sbin的差异类似,他们保存的不是基本二进制文件。在/lib中保存用于系统启动和应用于基本命令,而/usr/lib则保存其他的 lib,例如perl5在/usr/lib/perl5中有lib。
lib有四种格式:
-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来传递的。
在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