现在的位置: 首页 > 综合 > 正文

Linux-2.6.32.2内核在mini2440上的移植—-用busybox制作根文件系统

2013年07月07日 ⁄ 综合 ⁄ 共 7715字 ⁄ 字号 评论关闭

1、交叉编译Busybox

(1)、解压 busybox

clx@think:/work$ tar -jxvf busybox-1.20.0.tar.bz2 -C /work/armlinux

(2)、进入源码,修改Makefile文件:

修改:  
CROSS_COMPILE ?=arm-linux-   //第 164 行  
ARCH ?=arm //第 190 行  

(3)、配置 busybox

clx@think:/work/armlinux/busybox-1.20.0$ make menuconfig

选中[*] Build BusyBox as a static binary (no shared libs) 该选项用于选择是否使用静态编译方式。如果选择采用静态编译,则生成的busybox命令文件在运行时就不需要额外的函数库支持。为了简单起见,这里建议选择使用静态编译方式。

Busybox Settings  --->Busybox Library Tuning  ---> 保留Command line editing以支持命令行编辑;保留History size以支持记忆历史命令;选中Tab completion和Username completion以支持命令自动补全的设置采用默认设置

选项Applets,他将busybox的支持的几百个命令分门别类。我们只要在各个门类下选择想要的命令即可。这里我们基本保持默认设置。

(4)、编译busybox

首先创建一个新的目录rootfs,作为整个根文件系统的根目录

clx@think:/work/armlinux/busybox-1.20.0$ mkdir /work/armlinux/rootfs

编译 busybox 到rootfs目录下:

make CONFIG_PREFIX=/work/armlinux/rootfs install

clx@think:/work/armlinux/rootfs$ ls
bin  linuxrc  sbin  usr

安装完成后,可以看到在rootfs目录下生成了bin、sbin、usr/bin、usr/sbin目录以及一个linuxrc链接文件,其下包含了我们常用的命令,这些命令都是指向bin/busybox的软链接。

linuxrc是内核启动的init进程,那内核又如何知道要启动的init进程是哪个呢?它是由uboot传递给linux内核参数中"init=xxx"决定的。在我的目标板的uboot中传递给内核的参数为"init=/linuxrc"。内核如何启动init进程可以查看内核代码init/main.c中的init_post函数。

2、构建根文件

嵌入式 Linux 中都需要构建根文件系统,构建根文件系统的规则在 FHS(Filesystem Hierarchy Standard)文档中,下面是根文件系统顶层目录。  

目录   内容 

bin 存放所有用户都可以使用的、基本的命令。 
sbin   存放的是基本的系统命令,它们用于启动系统、修复系统等。 
usr   里面存放的是共享、只读的程序和数据。 
proc   这是个空目录,常作为 proc 文件系统的挂载点。 
dev   该目录存放设备文件和其它特殊文件。 
etc   存放系统配置文件,包括启动文件。 
lib   存放共享库和可加载块(即驱动程序),共享库用于启动系统、运行根文件系统中的可执行程序。
boot   引导加载程序使用的静态文件 
home   用户主目录,包括供服务账号锁使用的主目录,如 FTP 
mnt 用于临时挂接某个文件系统的挂接点,通常是空目录。也可以在里面创建空的子目录。 
opt 给主机额外安装软件所摆放的目录。 
root root 用户的主目录 
tmp   存放临时文件,通常是空目录。 
var   存放可变的数据。 

(1)、根据FHS标准依次创建各个子目录

clx@think:/work/armlinux/rootfs$mkdir root dev etc boot tmp var sys proc lib mnt home
clx@think:/work/armlinux/rootfs$mkdir etc/init.d etc/rc.d etc/sysconfig  
clx@think:/work/armlinux/rootfs$mkdir  usr/lib usr/modules  
clx@think:/work/armlinux/rootfs$mkdir mnt/etc mnt/jffs2 mnt/yaffs mnt/data mnt/temp  
clx@think:/work/armlinux/rootfs$mkdir var/lib var/lock var/run var/tmp  
clx@think:/work/armlinux/rootfs$chmod 1777 tmp  
clx@think:/work/armlinux/rootfs$chmod 1777 var/tmp 

改变了 tmp 目录的使用权,让它开启sticky 位,为 tmp目录的使用权开启此位,可确保tmp目录底下建立的文件,只有建立它的用户有权删除。尽管嵌入式系统多半是单用户,不过有些嵌入式应用不一定用 root 的权限来执行,因此需要遵照根文件系统权限位的基本规定来设计。 

注意:BusyBox作为静态库编译,后续自己开发的程序在编译选后加上 –static 也编译城静态,否则程序下载至目标板文件系统上可能报错:bin/sh: hello :not found,因为缺少某些必要的库,为了方便起见,在这里将其编译为动态链接。

选择上
Busybox Settings  --->
General Configuration  --->
[*] Don't use /usr

选中该项可以避免busybox 被安装到宿主系统的/usr目录下,破坏宿主系统

修改:  
CROSS_COMPILE ?=/opt/FriendlyARM/toolschain/4.4.3/bin/arm-linux-   //第 164 行  
make CONFIG_PREFIX=/work/armlinux/rootfs install
clx@think:/work/armlinux/rootfs$ ls
bin  linuxrc  sbin
clx@think:/work/armlinux/rootfs$ mkdir usr 
clx@think:/work/armlinux/rootfs$ mkdir usr/bin usr/lib usr/sbin lib/modules
构建lib库
虽然通过编译busybox生成了我们需要的可执行文件,但现在在目标板上仍然无法运行,需要添加lib库来支持可执行文件运行。可以使用uclibc和glibc来构建lib库。由于编译lib库相对复杂,而我们又有现成的lib库可以使用,这里我们就实行拿来主义。现成的lib库就在我们的交叉编译工具arm-linux-gcc的目录下,在本人主机上的绝对路径为/opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-gnueabi/lib,

此lib目录有下面这些东西:
1.目标文件,如crtn.o,用于gcc链接可执行文件
2.libtool库文件(.la),在链接库文件时这些文件会被用到,比如他们列出了当前库文件所依赖的其它库文件,程序运行时无需这些文件
3.gconv目录,里面是各种链接脚本,在编译应用程序时,他们用于指定程序的运行地址,各段的位置等 (我的4.1.2没有这个目录)
4.静态库文件(.a),例如libm.a,libc.a
5.动态库文件 (.so、.so.[0-9]*)
6.动态链接库加载器ld-2.3.6.so、ld-linux.so.2
7.其它目录及文件

很显然,第1、2、3、4、7类文件和目录是不需要拷贝的。
由于动态链接的应用程序本身并不含有它所调用的C库函数的代码,因此执行时需要动态链接库加载器来为它加载相应的C库文件,所以第6类文件是需要拷贝的。第5类文件当然要拷贝。 

cp $file-*.so rootfs/lib
cp -d $file.so.[*0-9] rootfs/lib
cp -d ld*.so* rootfs/lib

把该lib目录下的所有文件复制到目标板文件系统lib下,执行命令:
#cp -f /opt/FriendlyARM/toolschain/4.4.3/arm-none-linux-g
nueabi/lib/ *.so* /work/armlinux/rootfs/lib
-a

(2)、构建etc目录(可将busybox-1.20.0/examples/bootfloppy/etc/下的文件拷贝到etc目录下

a、创建etc/inittab

init进程根据/etc/inittab文件来创建其他子进程,比如调用脚本文件配置ip地址、挂接其他文件系统,最后启动shell等。

clx@think:/work/armlinux/rootfs/etc$
cp /work/armlinux/busybox-1.20.0/examples/inittab /work/armlinux/rootfs/etc

修改里面内容,屏蔽掉不需要的

#etc/inittab  

#制定系统启动时要执行 rcS 脚本
::sysinit:/etc/init.d/rcS                            
#指定打开一个无需登陆验证的shell,以s3c2410_serial0为控制台 
s3c2410_serial0::askfirst:-/bin/sh    
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

b、创建etc/init.d/rcS文件

 rcS文件是一个脚本文件,借助启动脚本可以设置各种程序开机后自动运行,也可进行其他系统设置,这有点类似于Windows系统中的Autobat自动批处理文件。如果想把自己编写的应用程序设置为开机启动,在本文件中中加入运行该程序的命令即可

#!/bin/sh
echo "Processing /etc/init.d/rcS"
echo "mount -a"
mount -a #mount上fstab文件中所有文件系统
exec /etc/rc.local

使用以下命令改变rcS的执行权限:

clx@think:/work/armlinux/rootfs/etc/init.d$ chmod +x rcS

c、在etc/sysconfig目录下新建文件HOSTNAME,内容为”MINI2440”,设置主机名字

d、创建/etc/rc.local 文件

/etc/rc.local是被init.d/rcS 文件调用执行的特殊文件,与Linux 系统硬件平台相关,如安装核心模块、进行网络配置、运行应用程序、启动图形界面等。

#!/bin/sh
echo "Processing /etc/rc.local"
echo "get hostname"
/bin/hostname -F /etc/sysconfig/HOSTNAME

echo "Starting mdev"
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
echo "ifconfig eth0 192.168.1.250"
ifconfig eth0 192.168.1.250
echo "DeramCatcher"  
echo "Date:2013.5.14" 

clx@think:/work/armlinux/rootfs/etc/init.d$ chmod +x rc.local

e、创建etc/fstab文件

fstab文件描述系统中各种文件系统的信息,应用程序读取这个文件,然后根据其内容进行自动挂载的工作。创建的代码如下:

#device    mount-point     type      option     dump   fsck   order 
proc          /proc             proc      defaults     0        0  
none          /tmp            ramfs     defaults     0        0  
sysfs         /sys            sysfs     defaults      0        0  
mdev         /dev             ramfs     defaults      0        0

文件中各字段的意义如下:1)device:要挂接的设备,如/dev/mtdblockl;2)mount-point:挂接点;3)type:文件系统类型;4)opt-ions:挂接参数,以逗号隔开;5)dump和fsck
order:用来决定控制dump、fsck程序的行为。

f、创建etc/profile文件

#/etc/profile
echo "Processing /etc/profile"
echo "set user path"
PATH=/bin:/sbin:/usr/bin:/usr/sbin 
echo "set search library path"
LD_LIBRARY_PATH=/lib:/usr/lib
echo "set PS1" 
PS1='[\u@\h:\w]\$'
#PS1='[$USER@\h:\w]\$'
HOSTNAME='/bin/hostname'

export PATH LD_LIBRARY_PATH HOSTNAME PS1 

g、创建etc/mdev.conf文件

mdev.conf可以用来控制设备节点的所有者和权限,格式如下:
<device regex> <uid>:<gid> <octal permissions> 
mdev.conf还可以设置mdev在dev目录下生成的设备节点的名字,如果该文件不存在,那么在执行mdev –s这个命令时,会提示找不到mdev.conf。我们不需要mdev规则,所以只是touch生成一个空文件就OK了。当然也可以根据mdev的规则来 编写mdev.conf。

g、创建用户和组文件

拷贝主机etc目录下的passwd、group、shadow文件到 rootfs/etc目录下

(3)、构建dev目录

这里使用busybox的mdev创建设备文件,mdev是udev的简化版本,它也是通过读取内核信息来创建设备文件。
要使用mdev,需要内核支持sysfs文件系统,为了减少对Flash的读写,还要支持tmpfs文件系统。先确保内核已经设置了CONFIG_SYSFS、CONFIG_TMPFS配置项。
使用mdev的命令如下,请参考它们的注释以了解其作用:
#mount -t tmpfs mdev /dev (使用内存文件系统,减少对Flash的读写)
#mkdir /dev/pts (dev/pts用来支持外部网络连接(telnet)的虚拟终端)
#mount -t devpts devpts /dev/pts
#mount -t sysfs sysfs /sys (mdev通过sysfs文件系统获得设备信息)
#echo /bin/mdev > /proc/sys/kernel/hotplug (设置内核,当有设备插拔时调用/bin/mdev程序)
#mdev -s (在/dev目录下生成内核支持的所有设备的节点)
要在内核启动后,自动运行mdev。需要修改etc目录下的两个文件:修改etc/fstab来自动挂载文件系统、修改etc/init.d/rcS加入要自动运行的命令。参考之前的文件,已经修改。

从Linux-2.6.18开始,负责旧版本的设备管理系统devfs已被废除,但新版本的udev是一个基于用户空间的设备管理系统。在内核启动时并不能自动创建设备节点,固需手动创建console和null两个启动过程必须的设备节点。将采用busybox中内置的mdev,一个简化的udev版本。

clx@think:/work/armlinux/rootfs$ sudo mknod -m 600 dev/console c 5 1
clx@think:/work/armlinux/rootfs$ sudo mknod -m 600 dev/null c 1 3

mknod建立一个目录项和一个特殊文件的  对应索引节点:语 法   mknod[必要参数][选择参数][主设  备号][次设备号],建立的文件有三种 b:块设备 c:字符设备   p:管道文件
如果不创建这两个设备文件,在文件系统启动时会出现错误信息,不能初始化控制台。


3、制作根文件系统映像文件

clx@think:/work/armlinux$ sudo tar zxvf mkyaffs2image.tgz -C /
usr/sbin/mkyaffs2image
usr/sbin/mkyaffs2image-128M

clx@think:/work/armlinux$ sudo mkyaffs2image-128M rootfs rootfs.img

4、编译测试

Please press Enter to activate this console. eth0: link up, 100Mbps, full-duplex, lpa 0xCDE1

Processing /etc/profile
set user path
set search library path
set PS1
root@MINI2440:/# ls
bin         etc         linuxrc     proc        sys         var
boot        home        lost+found  root        tmp
dev         lib         mnt         sbin        usr

root@MINI2440:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:90:90:90:90:90  
          inet addr:192.168.1.250 Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:63 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:6919 (6.7 KiB)  TX bytes:0 (0.0 B)
          Interrupt:51 Base address:0xe300 


注:在后续的使用中存在的一些问题

1、不能卸载驱动模块,运行modinfo显示不出模块信息

解决的方法,编译内核模块,并且要安装到文件系统中去。是安装在lib/modules/下面,此时这个目录下还是空的。

make modules_install ARCH=arm INSTALL_MOD_PATH=/xxx/rootfs
INSTALL_MOD_PATH是指定安装的路径。

这种方法只是解决了运行modinfo的问题,内核模块无法卸载的原因还没有找到


抱歉!评论已关闭.