ARM Linux根文件系统Root Filesystem的制作

发布者:ByteWanderer最新更新时间:2016-06-16 来源: eefocus关键字:ARM  Linux  根文件系统  Root  Filesystem 手机看文章 扫描二维码
随时随地手机看文章
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-gcc
AR = /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格式映像。
关键字:ARM  Linux  根文件系统  Root  Filesystem 引用地址:ARM Linux根文件系统Root Filesystem的制作

上一篇:arm Linux系统启动之start_kernel函数
下一篇:Ubuntu配置安装ARM Linux交叉编译环境完整流程

推荐阅读最新更新时间:2024-03-16 14:57

64位ARM处理器意味着什么?
   64位计算的历史相当丰富有趣。Cray等公司在70年代就已经开始在自己的系统当中使用64位寄存器,但真正纯粹的64位计算直到90年代才真正到来。 首先是MIPS的R4000,然后是DEC的Alpha处理器。到90年代中期,英特尔和Sun都已经拥有64位设计。而对于消费者来说,真正的转折点是 AMD在2003年发布了一款兼容英特尔32位x86处理器的64位PC处理器。 再向前快进10年,PC销量不断下滑,大部分智能手机和平板电脑都拥有了主频在1-2GHz之间的多核心处理器。但它们使用的都是32位架构,而非现代PC和服务器所使用的64位架构。到现在为止,这都是可以接受的。智能手机并不会去和PC拼性能,这些处理器需要足够节能,以
[手机便携]
tmux在ARM上的移植
当使用超级终端或者Minicom通过串口去调试ARM的时候,只能使用一个终端,不能像在Linux PC机上同时打开多个终端,这为我们同时执行或者调试多个程序带来不便;当然你可以让某些程序在后台执行,但是有没有更好的办法呢? 在Linux PC机上我们可以使用GNU Screen对终端进行复用,不过GNU Screen移植到ARM还是比较困难的。而且还有比GNU Screen更好的终端复用器,就是我们今天要用到的tmux. 我选择移植的版本是tmux-1.2,从tmux-1.2开始,它依赖于libevent包,当然,它还依赖于ncurses. ncurses我之前都已经移植好了的,这里就不说了。 一
[单片机]
tmux在<font color='red'>ARM</font>上的移植
ARMCC和GCC编译ARM代码的软浮点和硬浮点问题
本文介绍了ARM代码编译时的软浮点(soft-float)和硬浮点(hard-float)的编译以及链接实现时的不同。从VFP浮点单元的引入到软浮点(soft-float)和硬浮点(hard-float)的概念,然后是在GCC和ARMCC RVCT工具链下的具体编译参数。 VFP (vector floating-point) 从ARMv5开始,就有可选的 Vector Floating Point (VFP) 模块,当然最新的如 Cortex-A8, Cortex-A9 和 Cortex-A5 可以配置成不带VFP的模式供芯片厂商选择。VFP经过若干年的发展,有VFPv2 (一些 ARM9 / ARM11)、 VFPv3-D16
[单片机]
ARM汇编中LDR与LTORG的关系
看了arm汇编语言语法一个多月了。总算入门了。当然还有很多东西值得继续努力推敲滴。 最近对LDR与LTORG有了一些新的认识。 LDR是一个比较复制的指令。作用是从存储器到寄存器的单一数据读取指令。它有19条指令格式。 其中有两条格式为宏指令(macro),格式如下: 1,LDR cond type Rd, label 2,LDR cond Rd,= 32-bit-value 这里重点分析下第二条宏指令。它会被编译器编译成一条指令,把给定的32位数值保存到寄存器Rd.通常这掉指令是LDR cond Rd, ,这个32位数保存在以地址(pc+ offset 开始的一个文字池(literal pool
[单片机]
基于ARM智能建筑物裂纹实时测量系统开发研究
0 引 言 在建筑业中,评价墙体裂纹,地面裂纹是评价房屋质量的一项重要指标。由于传统的利用手工标尺进行裂纹宽度测量的方法既不准确又不方便,于是将嵌入式应用于自动测量建筑裂纹宽度成为了许多研究者的重要研究内容。 本研究将问题划分为以下两个部分: (1)裂纹宽度测量算法; (2)将以上所开发软件移植到ARM开发板,并优化算法提高软件运行速度。 1 裂纹宽度测量算法 计算裂缝宽度关键是要利用图像分割技术得到裂缝的真正边缘。虽然已有文献介绍了多种分割方法,但是未见有针对裂缝测试仪采集到的裂缝图像进行处理的方法。因此,本文针对裂缝图像,提出了结合OTSU图像分割与Sobel边缘检测的混合算法进行裂纹检测与宽度
[单片机]
嵌入式linux开发 (十三) FLASH(3) s3c2440外扩NAND FLASH
- JZ2440 S3C2440 ARM920T -内置 Steppingstone (4K-Byte SRAM) 无rom -外扩 MX29LV160DBTI:2MB,并口 NOR FLASH K9F2G08U0C: 256MB,NAND FLASH soc The S3C2440A is developed with ARM920T core, 0.13um CMOS standard cells and a memory complier. The ARM920T implements MMU, AMBA BUS, and Harvard cache architecture with sep
[单片机]
ARM单片机寄存器地址为什么相差4
上图是LPC1114用户手册系统控制模块(SYSCON)中的部分寄存器,请看红色框内,地址相差0x4。 上图是STM32内部RCC寄存器的部分寄存器,请看红色框内,地址相差0x4。 为什么会相差4?很多初学者问我这个问题,高手就请绕过吧。 计算机、单片机都是以字节为单位进行存储的。这里的4就是4个字节的意思。上面列举的LPC1114是ARM Cortex-M0内核,STM32是ARM Cortex-M3内核,这两ARM单片机都是32位的。1个字节是8位,4个字节就是32位。32位单片机的寄存器基本上是32位的,8位单片机的寄存器基本上也是8位的。 打开你曾经用过的reg51.h文件,看看普通51单片机的寄存器地址映射,一共不
[单片机]
<font color='red'>ARM</font>单片机寄存器地址为什么相差4
爱特梅尔基于ARM9产品支持Android操作系统
微控制器及触摸解决方案的领导厂商爱特梅尔公司(Atmel® Corporation)宣布其基于ARM®的产品SAM9G45和SAM9M10将支持Android™ 操作系统 ,应用于消费、工业和计算市场。爱特梅尔以32位ARM926处理器为基础的SAM9G45和SAM9M10 ARM9™器件现可兼容Android操作系统,为运行Android操作系统的SAM9M10-G45-EK板提供完整的板级支持包(board support package, BSP)。 Android操作系统正在成为嵌入式开发人员的首选操作系统,不仅用于手机和平板电脑市场,也包括家用电器、工业设备监视器和医疗设备等垂直市场。相比传统Linux®版本,
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved