http://xianzilu.spaces.live.com/blog/fakehandlerpage.aspx?wa=wsignin1.0
http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!290.entry
关于根文件体系的制造,网络上有许多文章,大多数都只讲到建几个目录,然后用Busybox做个Shell,有许多要害的东西没有说。通过很长时刻的摸爬滚打,我总算能够自食其力树立一个根文件体系了。其实我也不懂得原理,仅仅告知咱们我的作法,其间也难免有过错,欢迎咱们纠正。
首要介绍根文件体系的组成:目录、Shell、库、脚本,一个个来。
- 目录
根文件体系要包括这些有必要有的目录:/dev、/bin、/usr、/sbin、/lib、/etc、/proc、/sys/dev是devfs(设备文件体系)或许udev的挂在点地点。在运用devfs的内核里假如没有/dev,底子见不到Shell发动的信息,由于内核找不到/dev/console;在运用udev的体系里,也事前需求在/dev下树立console和null这两个节点。关于devfs和udev的差异,网上许多文章说。当然假如你的内核现已不支撑devfs了(2.6.12今后),能够运用纯纯的静态节点。也便是用mknod人工生成。/bin、/usr/bin、/usr/sbin、/sbin是编译Busybox这个Shell时分就有的,用于寄存二进制可履行文件,就不多解说了。/lib用于寄存动态链接库。网上许多文章都说静态编译Busybox,能够省去建库的费事进程。这样做只能让Busybox发动,咱们自己写的,或许是编译的软件包仍是需求动态库的。除非悉数静态编译,你能够试试,一个Hello world就要几百k。关于库的内容后边仔细说。/etc是用来寄存初始化脚本和其他装备文件的。关于初始化脚本的内容后边仔细说。/proc是用来挂载寄存体系信息虚拟文件体系——“proc文件体系”,“proc文件体系”在内核里边能够选。假如没有“proc文件体系”,许多Shell自己的指令就没有方法运转,比方ifconfig。“proc文件体系”不像devfs能够主动挂载,它需求运用初始化脚本挂载。别的,udev也需求“proc文件体系”的支撑。/sys用于挂载“sysfs文件体系”,“sysfs文件体系”在内核里边能够选。现在我以为它便是给udev供给支撑的,。“sysfs文件体系”也需求运用初始化脚本挂载。别的还能够有/tmp、/mnt、/swp、/var这样的不是嵌入式体系有必要的目录,在说完Shell的制造之后,我再谈树立目录的作业。
- Shell
Shell很简略,便是Busybox,上网下载一个来:http://www.busybox.net/downloads/。说Busybox和arm-linux-gcc有兼容性问题,不过我觉得那是比较低版别的年代问题了,我用Busybox 1.8.2和arm-linux-gcc 3.4.1/3.3.2都能够。解压缩今后找到Makefile里边的ARCH和CROSS_COMPILE,改成:
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/3.4.1/bin/arm-linux-
当然CROSS_COMPILE由你自己的编译器方位决议,然后
# make menuconfig
# make
# make install
留意装备的时分把一些uCLinux Only的东西去掉,否则会错;装备的时分还能够修正装置方位,默许是在Busybox下的“_install”。之后就能够在Busybox生成的Shell基础上树立根文件体系了,我就用指令来说吧,Busybox在/home/lxz/busybox,根文件体系在/home/lxz/rootfs# mkdir /home/lxz/rootfs
# cd /home/lxz/busybox/_install
# cp -r ./ /home/lxz/rootfs# cd /home/lxz/rootfs
# mkdir dev
# mkdir etc
# mkdir lib
# mkdir proc
# mkdir sys
# mkdir tmp假如不必devfs,下面的指令是有必要的。有必要以root用户履行(用su指令能够切换为root,切换后用exit指令能够回来普通用户):# cd /home/lxz/rootfs/dev
# mknod -m 660 console c 5 1
# mknod -m 660 null c 1 3假如不运用devfs没有这两个静态节点,console的提示底子就看不到,呈现的现象或许是内核提示Free init memory: XXK之后,Warning: Unable to find a initial console之类的,详细的单词记住不是很精确。我没有试过运用udev的时分没有这两个静态节点的状况,横竖放了也不影响把/dev挂载为tmpfs。假如运用udev,还需求把udevd、udevstart、udevadmin这三个文件放到/sbin里边(我运用udev-117,网上介绍较多的udev-100有9个文件要放)。
- 库
库可是一件十分费事的事请。我主张初学者复制买的开发板里边带的文件体系的库,假如开发板的文件体系是映像,只需求把映像挂载在某个目录下就能够拜访,假定映像叫做rootfs.cramfs,能够这样# mkdir /home/lxz/evb_rootfs
(切换为root用户)
# mount -o loop rootfs.cramfs /home/lxz/evb_rootfs
(能够切换为普通用户)
# cd /home/lxz/evb_rootfs/lib
# cp -r ./ /home/lxz/rootfs/lib一般开发板里都会带有许多库,可是总体积却比较大。能够删掉一些不必的库来减小体积,可是,,我也不知道那些库详细含有什么函数,什么状况删什么;或许今后我会把这部分补上。假如觉得库体积太大,也能够自己编译glibc或许uclibc,可是这是十分繁琐的事请——现在我以为库应该和编译器arm-linux-gcc一同制造。有个傻瓜式的计划是运用cross-tool,下载地址:http://www.kegel.com/crosstool/。尽管cross-tool是用来制造穿插编译器的,可是其进程中生成的glibc却能够作为副产品为咱们所用。cross-tool的运用能够看我之前的这篇文章http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!274.entry。在成功制造了穿插编译器之后,就能够从cross-tool的目录里把glibc取出来,假定cross-tool的途径是/home/lxz/cross-tool,编译出的编译器叫做arm-linux-gnu-gcc,gcc版别3.4.5,glibc版别2.3.6,想要把glibc库复制到/home/lxz/glibc,下面的操作仍是用指令来阐明。# cd /home/lxz/cross-tool/build/arm-linux-gnu-gcc/gcc-3.4.5-glibc-2.3.6/build-glibc# ../glibc-2.3.6/configure –prefix=/home/lxz/glibc# make install等候装置完毕# cd /home/lxz/glibc# cp -r lib /home/lxz/rootfs这样就把glibc的大部队复制好了,可是这样还缺两个库,咱们持续# cd /home/lxz/cross-tool/build/arm-linux-gnu-gcc/gcc-3.4.5-glibc-2.3.6/build-gcc/gcc# cp libgcc_s.so* /home/lxz/rootfs/lib还短少一个libtermcap库,这个就略微有些费事。libtermcap-2.0.8-35-armv4l源码包的下载地址是http://www.netwinder.org/mirror/pub/netwinder/SRPMS/nw/9/libtermcap-2.0.8-35.src.rpm,你也能够在这里http://www.netwinder.org/allsrpms.html找到其他版别的。假定libtermcap-2.0.8-35.src.rpm下载到了/home/lxz/libtermcap,下面持续用指令阐明。# cd /home/lxz/libtermcap# rpm2cpio libtermcap-2.0.8-35.src.rpm | cpio -ivd
# tar xvjf termcap-2.0.8.tar.bz2
接下来要打13个补丁,很汗啊,请必定依照下面的次序来打补丁# patch -p0 -i termcap-2.0.8-shared.patch
# patch -p0 -i termcap-2.0.8-setuid.patch
# patch -p0 -i termcap-2.0.8-instnoroot.patch
# patch -p0 -i termcap-2.0.8-compat21.patch
# patch -p0 -i termcap-2.0.8-xref.patch
# patch -p0 -i termcap-2.0.8-fix-tc.patch
# patch -p0 -i termcap-2.0.8-ignore-p.patch
# patch -p0 -i termcap-buffer.patch
# patch -p0 -i termcap-2.0.8-bufsize.patch
# patch -p0 -i termcap-2.0.8-colon.patch
# patch -p0 -i libtermcap-aaargh.patch
# patch -p0 -i termcap-2.0.8-glibc22.patch
# patch -p0 -i libtermcap-2.0.8-ia64.patch然后到/home/lxz/libtermcap/termcap-2.0.8里,找到Makefile,修正其间的CC和AR,CC = /usr/local/arm/3.4.1/bin/arm-linux-gccAR = /usr/local/arm/3.4.1/bin/arm-linux-ar当然,你的编译器在哪里就改成相应的内容。假如嫌费事,能够从本站材料页面下载我现已打好补丁,修正好Makefile的包,地址http://cosine.oicp.net/project/common/termcap-2.0.8.tar.bz2。需求留意的是,这个包里CC = arm-linux-gcc、AR = arm-linux-ar,请设置好缺省途径。然后就能够编译了:# cd /home/lxz/libtermcap/termcap-2.0.8# make# ln -s libtermcap.so.2.0.8 libtermcap.so.2# cp libtermcap.so* /home/lxz/rootfs/lib这样,Shell发动所需求的底子库就都备齐了。可是,这些库里边还含有调试信息,体积稍大,能够把这些信息去掉(当然不去掉也没有什么影响)。# cd /home/lxz/rootfs/lib# arm-linux-strip *.so*至此,库就制造好了。
- 脚本
有了以上的东西,Shell仍是不能正常作业。或许会是内核提示Free init memory: XXK之后就什么输出也没有了,这时分向终端敲入文字,能够显现;便是没有终端提示符,不理睬输入的指令。这是由于初始化脚本没有发动Shell。下面介绍这些脚本。首要是/etc/inittab。内核发动、根文件体系挂载之后一切必要的一个文件,其间列举了Shell和整个体系初始化、封闭所需的指令。假如你想让Shell呈现,那么只需求参加这么一行“::askfirst:/bin/ash”。当然假如在编译Busybox的时分挑选的shell不是“ash”,而是hush、lash、msh之类,那就改成相应的东西。除了发动Shell,inittab还干了许多作业,我就用我的inittab来阐明晰。留意,在编译Busybox的时分要选上touch、syslogd、klogd等指令。# Startup the system
null::sysinit:/bin/mount -o remount,rw /
null::sysinit:/bin/mount -t proc proc /proc
null::sysinit:/bin/mount -a
null::sysinit:/bin/hostname -F /etc/hostname# Now run any rc scripts
::sysinit:/etc/init.d/rcS# Now invoke shell
::askfirst:/bin/ash# Logging junk
null::sysinit:/bin/touch /var/log/messages
null::respawn:/sbin/syslogd -n -m 0
null::respawn:/sbin/klogd -n# Stuff to do for the 3-finger salute
::ctrlaltdel:/sbin/reboot# Stuff to do before rebooting
null::shutdown:/usr/bin/killall klogd
null::shutdown:/usr/bin/killall syslogd
null::shutdown:/bin/umount -a -r
null::shutdown:/sbin/swapoff -a好,把上面这些储存为inittab,发动体系。应该呈现两个提示,没有/etc/fstab和/etc/init.d/rcS。现在我的了解/etc/fstab是用来履行mount -a指令的,里边是文件体系的挂载表。仍是用我的fstab来阐明。#/dev/root / ext2 rw,noauto 0 1
proc /proc proc defaults 0 0
devpts /dev/pts devpts defaults,gid=5,mode=620 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0还有/etc/init.d/rcS,这在PC上是用来履行/etc/init.d下一切初始化脚本的一个脚本,,请原谅我不懂得怎样写这种脚本,关于嵌入式体系,底子不需求这么杂乱,直接写在/etc/init.d/rcS里边了。仍是用我的/etc/init.d/rcS来阐明,其间发动udev的那些指令关于运用静态设备节点和devfs的体系不适用。# Start udev
/bin/mount -t tmpfs tmpfs /dev
/sbin/udevd –daemon
/sbin/udevstart# Configure net interface
/sbin/ifconfig lo 127.0.0.1 up
/sbin/route add -net 127.0.0.0 netmask 255.0.0.0 lo
/sbin/ifconfig eth0 192.168.2.25 netmask 255.255.255.0
/sbin/route add default gw 192.168.2.1假如用的是udev,还有必要有udev的装备脚本。这个写起来有些费事,咱们能够直接用udev自己带的那些脚本,方位在udev目录下的etc/udev/udev.conf和etc/udev/rules.d里边的文件。把这些放到根文件体系中去,etc/udev/udev.conf变为根文件体系的/etc/udev/udev.conf,etc/udev/rules.d里边的文件变为/etc/udev/rules.d里边的文件。
至此,一个可用的最简略文件体系就完成了。之后,能够运用mkcramfs、mkyaffs之类的东西制造文件映像,这我就不多说了。需求留意的是,cramfs文件体系是只读的,就算用的是initrd加载的cramfs也相同是只读的,这对根文件体系的/var目录有必定的影响。除了本文中说的方法,还能够用buildroot这个东西来建,可是现在我还在测验中,今后再说。假如你嫌上面的这一切都很费事,能够从本站材料站下载我给Linux 2.6.19内核做的最简文件体系(1.5M),地址是http://cosine.oicp.net/project/at91rm9200/root.img,cramfs格局映像。