1 引言
1.1 交叉编译环境
交叉编译环境:arm-linux-gcc4.3.2。
2 建立目录结构
建立目标板的根文件系统目录结构过程中,可以参照《FilesystemHierarchy Standard》(FHS)规则标准,规范自已的目录层次结构,大部分作为工作站和服务器的Linux主机上的根文件系统目录结构通常遵守该标准,例如我们自已的Fedora--Linux主机。然而,作为根据用户需求定制的嵌入式Linux系统不必严格遵循该标准,但并不代表可以违反其中的所有规则,只是意味着破坏某些规则对系统的正常操作几乎没有影响。首先,表2.1列出根文件系统顶层目录的完整清单以及FHS指定的内容。
目录 | 内容 |
bin | 必要的用户命令(二进制文件) |
boot | 引导加载程序使用的静态文件 |
dev | 设备文件和其他特殊文件 |
etc | 系统配置文件,包括启动文件 |
etc | 系统配置文件,包括启动文件 |
home | 用户主目录,包括供服务账号所使用的主目录,例如FTP |
lib | 必要的链接库,例如C链接库、内核模块 |
mnt | 安装点,用于暂时安装文件系统 |
opt | 附加的软件套件 |
proc | 用来提供内核与进程信息的虚拟文件系统 |
root | root用户的主目录 |
sbin | 必要的系统管理员命令 |
tmp | 暂时性的文件 |
usr | 在第二层包含对大多数用户都有用的大量应用程序和文件、包括X服务器 |
var | 监控程序和工具程序所存放的可变数据 |
表2.1根文件系统顶层目录
目标板上根文件系统通常不必具备所有的目录,然而,其中必不可少的目录结构有:
/bin、/dev、/etc、/lib、/proc、/sbin和/usr. Linuxrc
其他的目录可以根据实际情况进行移除,甚至可以添加用户自已定义的目录结构,尽管这不符合FHS的标准。在最小系统中的根文件系统中,除了设计了上述必须具备的目录,根据应用实际需求,需要部分目录结构的修改设计工作:
1) 增加/ftp目录,作为登录目标板ftp服务器端时的特定目录;
2) 保留/home目录,以支持增加系统用户;
3) 保留/mnt目录,以支持应用挂载用户文件系统;
4) 保留/sys目录,以支持动态加载驱动模块功能mdev;
5) 保留/tmp目录,为应用提供存放临时性文件的目录空间;
6) 保留/var目录,为应用提供存放可变数据的目录空间;
7) 在/usr目录下,增加bin、sbin和lib二级目录,分别用于存放用户可能需要的二进制文件、系统管理员可能需要的二进制文件和非必要的链接库;
8) 在/var目录下,增加log和run二级目录,分别用于存放系统信息log和系统启动信息可变数据
9) 在/mnt目录下,增加user1和user2二级目录,挂载两个flash分区。
建立根文件系统的具体实现步骤:
1) 进入根文件系统所在目录;
# cd /rootfs
2) 建立根文件系统顶层目录;
# mkdir bin devetc ftp home lib mnt proc sbin sys tmp usr var
3) 建立/usr目录结构;
# mkdirusr/bin usr/lib usr/sbin
4) 建立/var目录结构;
# mkdirvar/log var/run
根据实际应用需求修改后,目标板的根文件系统目录结构如图2.1示:
图2.1 目标板根文件系统目录结构
3 添加系统文件
目标板上的根文件系统必须包含支持Linux操作系统正常运行的基本内容,包括必要的应用程序、应用程序所依赖的库以及相关的设备文件等。本章节将分步讲述添加这些系统文件的过程。
3.1 添加共享链接库
根文件系统的库文件存放在/lib目录下,是开发应用程序时使用的以及这些应用程序赖以在目标板上正常运行的链接库。在移植目标板根文件系统的过程中,采用开发套件ELDK4.2中的glibc库套件来建立目标板上的链接库。在开发套件/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib目录下:
包含四种类型的文件:
1) 实际的共享链接库
格式为libLIBRARY_NAME-GLIBC_VERSION.so,其中LIBRARY_NAME是链接库的名称,GLIBC_VERSION是glibc套件的版本编号。例如,glibc2.6的数学链接库的名称为libm-2.6.so。
2) 主修订版本的符号链接
名称格式为libLIBRARY_NAME.so.MAJOR_REVISION_VERSION,其中MAJOR_REVISION_VERSION是链接库的主修订版本编号,以实际的C链接库libc-2.6.so的符号链接库名称为libc.so.6。libdl-2.6.so则是libdl.so.2,程序一旦链接了特定的链接库,它将会参用其符号链接,程序启动时,加载器在加载程序之前,会因此加载该文件。
3) 与版本无关的符号链接指向主修订版本的符号链接
格式为libLIBRARY_NAME.so,主要功能是为需要链接特定链接库的所有程序提供一个通用的条目,与主修订版编号或glibc涉及的版本无关。例如,libm.so指向libm.so.6,libm.so.6指向实际的共享链接库libm-2.6.so。
4) 静态链接库包文件
格式为libLIBRARY_NAEM.a选择以静态方式链接链接库的应用程序便会使用这些包文件。例如libdl的静态包文件就是libdl.a。
除了链接库文件,还需要复制动态链接器及其符号链接,格式通常为ld-GLIBC_VERSION.so以及ld.so. MAJOR_REVISION_VERSION,在目标板的根文件系统中为ld-2.6.so和ld.so.1。
开发套件中包含了大量共享链接库,实际应用中不需要全部包含进来,否则可能导致根文件系统过于宠大,可以通过使用开发套件中的ldd命令或跨平台readelf命令找出应用程序依存哪些共享链接库。如
# arm-linux-readelf-a bin/busybox | grep "Sharedlibrary"
0x00000001(NEEDED) Sharedlibrary: [libm.so.6]
0x00000001(NEEDED) Shared library:[libc.so.6]
所以,需要将libm库和libc库及其符号链接复制到根文件系统/lib目录下。在决定需要哪些链接库组件之后,便可以将这些链接库组件和相关的符号链接复制到目标板根文系统中的/lib目录下,依次使用以下方法实现:
#cp /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib/libLIBRARY_NAME-*.so rootfs/lib
# cp –d /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib/libLIBRARY_NAME.so.[*0-9] /rootfs/lib
分别复制实际的共享链接库及其主修订版本的符号链接到目标板的根文件系统中。
然后,使用开发套件中的跨平台strip工具程序缩减所安装的链接库的尺寸:
# arm-linux-linux-strip/rootfs/lib/*.so
之后,应用程序就可以在运行时使用它们。
尽管uClibc也如同glibc一样包含了若干链接库,其各个组件的名称和用法如同glibc中相应的组件,且结构紧凑,容量甚小,是glibc的替代品,然而在eldk4.2中暂时还没有对uClibc的支持,所以,此处不作详述。
3.2 添加设备文件
在Linux系统中,几乎任何对象(包括设备)都可视为文件。在根文件系统中,所有设备文件(设备节点)都放在/dev目录里。大多数的工作站和服务器发行套件为/dev目录附带了数量宠大的文件内容。然而,在嵌入式Linux系统目标板上,通常只需要建立让系统正常操作的必要的条目即可。并且,在eldk开发套件的/dev目录下,包含了大多数目标板可能需要的设备文件。所以,在决定需要添加哪些设备文件后,首先可以从eldk开发套件获得大多数基本的设备文件,然后再加入根据平台特点自已创建的设备文件。
其中,除了最基本的设备文件条目,如表3.1所示。
文件名 | 说明 |
mem | 物理内存存取 |
null | null设备 |
zero | 以null byte为数据来源 |
random | 真随机数产生器 |
tty0 | 现行的虚拟控制台 |
tty1 | 第一个虚拟控制台 |
ttyS0 | 第一个UART串行端口 |
tty | 现行的TTY设备 |
console | 系统控制台 |
表3.1 基本的设备文件条目
还有其他的tty设备节点文件、mtd设备节点文件以及自已创建的flash设备节点文件等。除了需要自已创建的flash设备节点文件,其他文件均可以从eldk开发套件中获取,只需将其复制到根文件系统的/dev目录下。
除了基本的设备文件,可能还需要一些与它们相关的符号链接,使用ln –s命令来建立符号链接,例如进入到根文件系统/dev目录后,
# ln –s nullmouse
mouse为符号链接名称,null为链接指向的实际设备文件;
# ln –s flasha1flash_monitor
flash_monitor为符号链接名称,flasha1为链接指向的实际设备文件。
1 移植BusyBox
BusyBox 是很多标准 Linux® 工具的一个单个可执行实现。BusyBox 包含了一些简单的工具,例如 cat 和 echo,还包含了一些更大、更复杂的工具,例如 grep、find、mount 以及 telnet(不过它的选项比传统的版本要少);有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。BusyBox集成了大部分常用Linux命令的功能,而大小却只有1M左右,所以BusyBox非常适合应用于资源紧张的嵌入式系统。在最小系统中,引入BusyBox所要做的工作就是根据应用配置BusyBox选项,交叉编译BusyBox,将安装BusyBox生成的文件增加到根文件系统中来。
在http://www.busybox.net/网站下载最新的busybox,开发期间下载稳定版本为V1.21.1。
首先,设置交叉编译环境的路径。
# export PATH=$PATH:/urs/local/arm/4.3.2/bin/
# export CROSS_COMPILE=arm-linux-
或者把Makefile的CROSS_COMPILE 及ARCH改成如下:
CROSS_COMPILE ?= arm-linux-
ARCH ?= arm
进入busybox-1.21.1所在目录,进行配置busybox,执行make menuconfig。
# make menuconfig
配置选项只需要修改一项,其它都不做修改,如下操作:进入【Shells】修改与shell相关的配置,反选【Hide message on interactive shell startup】一项,使得系统启动后在shell上显示busybox的版本信息,如下图,其他选项不做修改,选择【Exit】返回主界面。
1.1 交叉编译
完成BusyBox的配置后,接下来就是交叉编译并安装BusyBox。
# make install
进行安装,安装过程中,同时完成BusyBox的交叉编译。
安装BusyBox完成后,将在busybox-1.21.1目录下生成一个_install目录,进入_install目录查看,如图4.12,生成了文件夹bin、sbin、usr和busybox符号链接文件linuxrc。
图4.12 交叉编译生成的文件
1 初始化系统配置
按照FHS标准规范,与根文件系统初始化过程中相关的配置文件存放在根文件系统/etc目录下,通常,嵌入式系统中遵循此规范。
Linux在启动时执行第一个进程init进程,因为/sbin/init是/bin/busybox的符号链接,所以BusyBox是目标板系统上执行的第一个应用程序。BusyBox的init进程依次进行以下工作:
1) 为init设置信号处理进程;
2) 初始化控制台;
3) 剖析inittab文件、/etc/inittab文件;
4) 执行系统初始化命令行,缺省情况下使用/etc/init.d/rcS命令行;
5) 执行所有会导致init暂停的inittab命令(动作类型:wait);
6) 执行所有仅执行一次的inittab命令(动作类型:once)。
所以,在初始化控制台后,BusyBox会检查/etc/inittab是否存在,如果不存在,BusyBox会使用缺省的inittab配置,如果存在/etc/inittab文件,BusyBox将对其进行解析,将其中的命令记录在内部的数据结构。因此,可以利用/etc/inittab文件对系统进行初始化配置,作为系统应用的入口。
1.1 inittab文件配置
BusyBox支持的inittab文件格式包含4个域,每个域所代表的意义如图5.1所示。
图5.1 inittab文件格式
因此,与初始化配置密切相关的主要是action和process字段,动作类型action字段指定了BusyBox init能够识别的inittab动作类型,如表5.1所示。
目录 | 内容 |
sysinit | 为init提供初始化命令行的路径 |
respawn | 每当相应的进程终止执行便重新启动 |
askfirst | 类似respawn,不同的是它会在重新启动进程之前等待用户按下Enter键,同时促使init在控制台显示“Please press Enter to activate this console”信息,主要用途是减少系统上执行的终端应用程序的数量 |
wait | 告诉init必须等到相应的进程完成后才能继续执行 |
once | 仅执行相应的进程一次,而且不会等待它完成 |
ctrlaltdel | 当按下Ctrl-Alt-Delete组合键时,执行相应的进程 |
shutdown | 当系统关机时,执行相应的进程 |
restart | 当init重新启动时,执行相应的进程,通常此处执行的进程就是init本身 |
表5.1 inittab动作类型
按照inittab文件格式要求,根据实际应用,将其设计内容如下:
# This is run first except when booting in single-usermode.
::sysinit:/etc/rc.sh
# /bin/sh invocations on selected ttys
#
# Start an "askfirst" shell on /dev/ttyS1
#ttyS1::askfirst:-/bin/sh
#
# Start internet super daemon; do NOT background!
#::respawn:/usr/sbin/xinetd -stayalive -reuse -pidfile/tmp/xinetd.pid
# Start user application
#::respawn:/bin/application
# Must be last 'respawn' entry to avoid ^C problem
# Start a shell on the console
# Login shell freely
#::respawn:-/bin/sh
# Need username and passwd to login shell
::respawn:-/bin/login
# Execute /sbin/init if "init" restart
::restart:/sbin/init
# Unmount the filesystem when shutdown; and remount inread-only mode if unmount fail
::shutdown:/bin/umount -a -r
系统启动后,inittab执行以下动作:
1) 将/etc/rc.sh设成系统的初始化文件;
2) 要求使用用户名及密码登录shell,每次终止重新启动;
3) 如果init重新启动,将/sbin/init设成它会执行的程序;
4) 系统关机时执行umount命令卸载所有文件系统,并且在卸载失败时用只读模式重新安装以保护文件系统。
尽管BusyBox在缺少情况下会解析/etc/init.d/rcS命令行,但在我们的嵌入式系统中,将其路径简化并指向/etc/rc.sh文件,接下来讲述一个rc.sh文件的内容。
1.1 passwd文件配置
etc/passwd是存放用户的基本信息的口令文件,系统的每一个合法用户占据文件中的一行记录,每一行记录的格式包含7个域,每个域所代表的意义如图5.2所示。
图5.2 passwd文件格式
例如,以下是目标板上的passwd初始内容:
root:$1$HxGnRj/U$9H5idXxzzOXVwEM07NLUH/:0:0:root:/:/bin/sh
guet:$1$Y9hfHeSc$ZB0lww.jreR8n2m//CxTb.:0:0:root:/ftp:/bin/sh
hello::0:0:root:/:/bin/sh
bin:*:1:1:bin:/bin:
daemon:*:2:2:daemon:/sbin:
halt:*:7:0:halt:/sbin:/sbin/halt
hello::0:0:root:/:/bin/sh
ftp:*:14:50:FTP User:/
nobody:*:99:99:Nobody:/:
target:$1$fPk3ZvbV$LR7z/eWc8LS4gUOeBq5FD0:200:100:TestUser:/home:/bin/sh
1) 注册名为root的用户以root用户的权限登录shell,其工作目录为文件系统根目录;
2) 注册名为guet的用户以root用户的权限登录shell,其工作目录为/ftp;
3) 注册名为target的用户以普通用户的权限登录shell,其工作目录为文件系统根目录;
4) 注册名为hello的用户无需口令并以普通用户的权限登录shell,其工作目录为文件系统根目录;
5) 其他用户passwd字段为“*”,表示其帐号被系统查封,系统不允许持有该注册帐号的用户登录。
在进行增加用户、删减用户或修改用户口令信息后,系统将在该文件中记录这些信息。例如,可以通过BusyBox的adduser功能为系统添加注册帐号,使用BusyBox的passwd功能对其进行口令修改:
# adduser ppc
则passwd文件将增加一行注册名为“ppc”的记录:
ppc:x:1000:1000:Linux User,,,:/home/ppc:/bin/sh
列表显示“ppc”用户工作目录为/home/ppc,我们甚至可以手动编辑passwd文件,如修改“ppc”用户工作目录为根目录:
ppc:x:1000:1000:Linux User,,,:/:/bin/sh
然而,通常情况下,不建议手动修改passwd文件。使用BusyBox新增用户后,其用户口令信息将同时保存在/etc/shadow文件中,只有超级用户才有权限读取该文件。
配置完成后输入命令:输入命令:./mkyaffs2image /rootfs system.img,即可制作出用于烧写的文件系统了。
1 简单移植步骤
下载新版本的busybox,然后进行make menuconfig进行配置,配置完后执行make、make install,把生成的busybox直接替换到板子的busybox,修改执行权限即可,替换后如下图:增加了需要使用用户名、密码登陆。
[ 1.794944] s5p-tvout s5p-tvout: hpd status is cable removed
[ 1.806829] smdkc110-rtc smdkc110-rtc: rtc disabled, re-enabling
[ 1.811418] smdkc110-rtc smdkc110-rtc: setting system clock to 2013-10-28 23:57:07 UTC (1383004627)
[ 1.833776] yaffs: dev is 32505858 name is "mtdblock2"
[ 1.837458] yaffs: passed flags ""
[ 1.840835] yaffs: Attempting MTD mount on 31.2, "mtdblock2"
[ 1.846471] yaffs: auto selecting yaffs2
[ 2.019060] block 420 is bad
[ 2.234172] usb 1-1: configuration #1 chosen from 1 choice
[ 2.247115] hub 1-1:1.0: USB hub found
[ 2.253615] hub 1-1:1.0: 4 ports detected
[ 15.236880] yaffs_read_super: isCheckpointed 0
[ 15.239941] VFS: Mounted root (yaffs filesystem) on device 31:2.
[ 15.245959] Freeing init memory: 280K
(none) login: xiaoyj
Password:
login[1117]: root login on 'UNKNOWN'
BusyBox v1.21.1 (2013-10-24 09:51:22 HKT) built-in shell (ash)
Enter 'help' for a list of built-in commands.
[root@(none) /]#
更多精彩如:
s5pv210开发欢迎你的加入。 桂林电子科技大学 xiaoyj205@163.com