本来想把文件系统制作的过程系统的整理一下,发现离最终目的还有一段距离。所以,还是采取边实验边修改,尝试可能情况,最终完成常用的所有功能的移植。这
样,在具体应用中只需要做相应的裁减就可以了。为了搞清楚每一个功能部件的依赖关系,要从最小的功能出发,逐步添加功能。
linux的启动阶段分为两大阶段。第一个阶段从bootloader引导内核,至内核挂载root fs成功为止,这个阶段的一个标志就是如下打印信息:
vfs: mounted root (jffs2 filesystem).
freeing init memory: 100k
第二个阶段分为如下顺序:init --> getty --> login --> shell四个阶段。而成功的打印信息:
[root@listentec ~]#
当然,根据你设定的shell的ps1,显示也会有所不同。但最终成功都会打印出shell prompt。
init现在力求统一标准,最为常用的还是system v init和busybox init。system v
init是host上常用的,也是redhat的默认init。system v
init是比较复杂的,支持多级别启动。相对于嵌入式系统来说,有些复杂。busybox只支持一个级别,相对来说,更适合嵌入式系统应用。
login在选择上也有busybox login和tinylogin。而tinylogin要支持的好一点。
shell的选择上有busybox ash,也可以交叉编译出一个bash,这样的话bash的功能要强一点。
(1)创建根文件系统的基本目录结构
这个肯定要参考fhs。最初制作的时候,我认为直接用root用户创建就可以了,这个与host还是比较一致的。
[armlinux@lqm basicfs1]$ tree -l 1
.
|-- bin
|-- dev
|-- etc
|-- home
|-- lib
|-- mnt
|-- proc
|-- root
|-- rootfs
|-- sbin
|-- sys
|-- tmp
|-- usr
`-- var
也写了小的脚本:
[armlinux@lqm fs]$ cat mkrootfs.sh
#!/bin/bash
# make the basic root file system
# set the target documentation
rootfs=rootfs
true=1
false=0
# check whether the user is the root
is_root()
{
if [ `id -u` == 0 ]; then
return $true
else
return $false
fi
}
# must be the root
if is_root; then
echo "must be root to run this script."
exit 1
fi
# create the rootfs
mkdir $rootfs; cd $rootfs
mkdir -p bin dev etc lib/modules proc sbin sys usr/bin usr/lib usr/sbin tmp
# create the basic dev
mknod -m 600 dev/console c 5 1
mknod -m 666 dev/null c 1 3
# copy lib
cp -av ../simple_fs/lib
cp -av ../simple_fs/etc/* etc/
这个制作过程并不复杂。只是在最小的组织上还是有待考虑的。
(2)编译busybox
主要就是修改arch和cross,然后menuconfig,最后指定路径安装。这里有一个版本对应问题,我是选择了cross-3.4.1,编译没有问题。
screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.alt='click here to open new window\nctrl+mouse wheel to zoom in/out';}" onmouseover="if(this.width>screen.width*0.7) {this.resized=true; this.width=screen.width*0.7; this.style.cursor='hand'; this.alt='click here to open new window\nctrl+mouse wheel to zoom in/out';}" onclick="if(!this.resized) {return true;} else {window.open('');}" onmousewheel="return imgzoom(this);" alt="" />
文件:
busybox.rar
大小:
0kb
下载:
下载
(3)编译tinylogin
这里需要注意的是,不采用tinylogin自带的加密算法。需要改动的地方是:
diff -urn tinylogin-1.4.orig/makefile tinylogin-1.4/makefile
--- tinylogin-1.4.orig/makefile 2003-01-03 18:56:33.000000000 +0800
+++ tinylogin-1.4/makefile 2008-03-19 11:00:01.000000000 +0800
@@ -49,12 +49,12 @@
# this adds just 1.4k to the binary size (which is a _lot_ less then glibc nss
# costs). note that if you want hostname resolution to work with glibc, you
# still need the libnss_* libraries.
-use_system_pwd_grp = true
+use_system_pwd_grp = false
# setting this to `true' will cause tinylogin to directly use the system's
# shadow password functions. if you leave this off, tinylogin will use its
# own (probably smaller) shadow password functions.
-use_system_shadow = true
+use_system_shadow = false
# this enables compiling with dmalloc ( )
# which is an excellent public domain mem leak and malloc problem
@@ -73,7 +73,7 @@
# if you are running a cross compiler, you may want to set this
# to something more interesting, like "powerpc-linux-".
-cross =
+cross = /usr/local/arm/3.4.1/bin/arm-linux-
cc = $(cross)gcc
ar = $(cross)ar
striptool = $(cross)strip
这样就可以使用host的/etc/group /etc/passwd /etc/shadow了。
(3)/etc/下基本配置文件的探讨
如果你在bootloader的命令行参数中没有指定"init=filename",那么首先init默认执行的是/sbin/init,而该程序现在采用的busybox的init,具体的流程为:
·为init设置信号处理流程
·初始化控制台
·剖析inittab文件,/etc/inittab
·根据/etc/inittab文件的设置来进行初始化,缺省情况首先执行/etc/init.d/rcs。
·执行所有会导致init暂停的inittab命令(动作类型:wait)
·执行所有仅执行一次的inittab命令(动作类型:once)
一旦完成,init进程就会循环执行如下工作:
·执行所有终止时必须重新启动的inittab命令(动作类型:respawn)
·执行所有终止时必须重新启动但启动前必须先询问用户的inittab命令(动作类型:askfirst)
其实简单的说,就是找到init,然后读取inittab脚本来执行。如果没有inittab脚本,busybox会按照默认的值进行操作。
这里多说几句的是,no
init的错误是很普遍的。主要的原因有:一是没有找到init;二是找了了执行的init,但是没有执行权限,所以还是无法执行;三是找到了init,
并且可执行,但是如果是动态编译,对应的共享库有问题的话,也是无法执行程序的。基本的原因就这三个,你当然可以按照最小的文件系统的功能进行测试,只需
要一个bin文件(内含sh),一个dev文件夹(内含console),还有一个init脚本,指定exac
/bin/sh。测试成功的话,说明你的基本流程可以走通,然后就应该逐步增加功能了。
当然因为后续功能添加的时候,dev中还必须包含null。其他的设备文件则可以通过udev的简化版本mdev来实现了。这个地方需要注意的是mdev
对应脚本加载时的初始化顺序是非常重要的,并非随便写。在后面telnet
server移植设定的时候就遇到了这个问题。建议读一下mdev.txt,按照上面的流程来写,就没有问题。
·/etc/inittab 这是init读取的第一个文件,语法是比较晦涩的,功能的易读性上也不好。所以它只是提供了一个动作的入口,具体的功能实现都在执行的操作里。
[armlinux@lqm etc]$ cat inittab
::sysinit:/etc/init.d/rcs
::respawn:-/bin/login
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
·/etc/init.d/rcs
就是shell脚本了,所有的初始化信息都可以逐步加在这里。初步的rcs参考tekkaman ninja的就可以了。这个是我后来完成的一个,仍然是初级脚本。
[armlinux@lqm etc]$ cat init.d/rcs
#!/bin/sh
# initial environment
# mount /etc/fstab spcified device
/bin/mount -a
# mount devpts in order to use telnetd
/bin/mkdir /dev/pts
/bin/mount -t devpts devpts /dev/pts
# read the busybox docs: mdev.txt
/bin/mount -t sysfs sysfs /sys
/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
# when mdev is mounted, /sys can be umounted
/bin/umount /sys
# hostname setting
/bin/hostname listentec
# network setting
/sbin/ifconfig lo 127.0.0.1
/sbin/ifconfig eth0 192.168.1.100 netmask 255.255.255.0
/sbin/route add default gw 192.168.1.1
# adjust time
/usr/sbin/ntpdate 210.72.145.44
# nfs client
/bin/mount -o nolock,wsize=1024,rsize=1024 192.168.1.106:/home/armlinux/nfs /mnt/nfs
/bin/echo "nfs client is on now and the mounted point is /mnt/nfs"
# print the author information
/bin/echo
/bin/echo "********************************"
/bin/echo " made by lqm "
/bin/echo "********************************"
/bin/echo
·/etc/mdev.conf
这个可以为空,也可以根据mdev的配置语法来编写。但是必须要有,否则就会报错。
·/etc/fstab
这是mount -a要读取的文本。根据需要编写。
[armlinux@lqm etc]$ cat fstab
proc /proc proc defaults 0 0
mdev /dev tmpfs defaults 0 0
关于login的还有/etc/passwd, /etc/group, /etc/shadow,直接从host拷贝就可以了
阅读(557) | 评论(0) | 转发(0) |