项目基本结束,这个是其中系统裁减的一个总结文档,不知道有没有人感兴趣:)
=============================================
前言:
为了完成用户的需求,需制作一个完整的环境供AP运行,且存在一些约束条件。
关键字:
DOM
Kernel Busybox X-Window Window-Manager Interbase nvidia
cutdown
目标说明:
在一个64M的DOM(Disk on
module)上建立可以运行完整的AP的环境
约束条件:
1、可利用的总空间为64M,由DOM提供,但实际可用空间只有53-59M,原因可能与设备文件和DOM本身有关,未确定
2、显卡为nvidia系列
3、kernel选用2.4.20,没有使用redhat自带的版本。采集卡的Driver目前还只能在2.4.20的kernel下编译,由于其移植性较差,已经开始考虑重新整理成可适合kernelversion大于2.4.25的所有kernel,参考bttv的最新实现
4、数据库选用interbase系列,目前使用的为firebird-1.5(firebird为interbase的开源实现,接口和interbase基本相同)。
5、其他附属的功能要求,在后面的文档中会有说明
制作流程:
某些部分的原理和实现没有办法写的很全面,但基本上会提供一些url的连接,供相关人员参考。基本上按照制作流程来写,前后相互牵连的部分不做特别说明。
一、Kernel的选择和编译:
由于driver的缘故,只能使用2.4.20的kernel。2.4.20和2.4.25都有对Driver做过尝试,其他版本的kernel没有试过,应该是可以的,尚未确认。在2.6的kernel上无法编译,目前确定的原因是makefile有问题,估计做一些相应的修改还是可以的,可参考bttv的makefile(
http://linux.bytesex.org/v4l2/bttv.html)。
回到kernel上来,基本上的编译原则是尽量减去不需要的部分,以及除了一些需要临时加载的Driver尽量不要出现module。由于上面所说的理由,DOM中使用的kernel为原始的2.4.20,可以从
http://www.kernel.org下载,本文档的附加文件里也可以找到。
另外,由于需求的定义,系统启动时需要显示splash画面,所以kernel还需要加入bootsplash功能,这个功能是第三方提供的,作为补丁加入kernel。作法如下:
1、打内核补丁并编译内核
假设内核源文件安装在/usr/src/linux/。下载bootsplash
3.07(地址:
ftp://ftp.suse.com),然后:
yourbox:~ # cd
/usr/src/linux
yourbox:/usr/src/linux # patch -p1 <
/path/to/bootsplash-3.0.7-2.4.20-vanilla.diff
yourbox:/usr/src/linux
#
配置内核,如make menuconfig或make xconfig,在”Console drivers” ->
“Frame-Buffer support” 选择 “VESA VGA graphics console” 或其他与你的显卡相应的驱动。打开 “Use
splash screen instead of boot logo”. 在 “Block Devices”中打开”Initial Ramdisk
support”,保存配置并编译内核,将生成的内核拷到/boot
下,并修改lilo或grub的配置文件以使用新的内核来启动。
2、加入图片
下载并安装splash工具:
ftp://ftp.suse.com/pub/people/# cd ~/splash
# tar
xvjf
splashutils.tar.bz2
splashutils/
splashutils/Makefile
splashutils/splash.c
[..]
splashutils/ChangeLog
splashutils/COPYING
#
cd splashutils
# make splash
gcc -Os -Wall -c -o splash.o splash.c gcc -Os
-Wall -o splash splash.o
strip splash
# cp splash /sbin/
# cd
..
将图片及相关的信息加入到initrd中去:
/sbin/splash -s -f
/etc/bootsplash/themes/yourtheme/config/bootsplash-1024x768.cfg >>
/boot/initrd.splash
图片在附件文件中
3、运行lilo更新配置文件(grub就不用更新了),重新启动,如果一切正常,就可以看到启动画面了。同时会有这样一些信息:
vesafb:
framebuffer at 0xf0000000, mapped to 0xdc816000, size 65472k vesafb: mode is
1024x768x16, linelength=2048, pages=41 vesafb: protected mode interface info at
c000:5137 vesafb: scrolling: redraw
vesafb: directcolor: size=0:5:6:5,
shift=0:11:5:0 Looking for splash picture.... silenjpeg size 11165 bytes, found
(1024x768, 4912 bytes, v3) Got silent
jpeg.
kernel的config文件比较大,在附件中有,这里就不列举了。
编译过程:
1、获取2.4.20的原始kernel压缩包(linux-2.4.20.tar.bz2)
2、tar xvjpf linux-2.4.20.tar.bz2
3、cp config-2.4.20
(kernelsource)/.config #拷贝config-2.4.20到kernel
source所在目录中并以.config为新的文件名
4、cd (kernelsource)
5、make menuconfig
#不需要做任何改动,直接退出
6、make dep && make bzImage && make modules
&& make modules_install && make install
7、如果没有问题,继续下一步,如果有问题,请检查编译环境是否正确,并重复step 6
8、此时kernel已经编译完毕,需要做两件事情,一是保存将来放入DOM的文件,二是将当前的发行版的kernel换成2.4.20,以便后面的nvidia显卡dirver的正确编译。
9、创建一个保存目录,比如~/kernelbackup
10、cp (kernelsource)/arch/i386/boot/bzImage
~/kernelbackup # 保存kernel
11、cp /lib/modules/2.4.20 ~/kernelbackup/ -arf #
保存编译出的所有modules
12、如果当前的发行版使用的是grub,则修改/boot/grub/grub.conf(如果没有这个文件可以修改/boot/grub/menu.lst,都是一样的),如果是lilo,修改/etc/lilo.conf。下面是grub的修改说明,lilo的修改办法可以参考相关文档:
#
add below to your grub.conf
title new kernel(2.4.20) # title just, u can
modify it anywhere
root (hd0,0) # root setup
kernel
(hd0,0)/boot/bzImage-2.4.20 ro root=/dev/hda1 vga=791 splash=silent #
just.....
initrd (hd0,0)/boot/initrd.splash # splash that show when booting
of
OS
13、reboot
14、选择新的启动选项,检查是否正确
二、Shell的选择和编译:
到目前为止,kernel的裁减基本上结束,下面是shell的选择和编译。
对于linux而言,kernel只是提供系统调用接口,本身无法直接使用,需要外部shell的支持。一般shell有几种选择,如bash、ash、busybox等,由于busybox相对尺寸最小,而且提供了基本完整的功能,所以选择busybox做为系统的shell。详细信息参阅
www.busybox.net,附件中有目前使用的busybox版本。busybox的流程主要是编译和安装,从而联合kernel组成一个基本系统。
busybox的配置文件在附件中有,这里就不列举了。
编译过程:
和kernel基本相似
1、解压busybox
2、复制config到busybox源码目录下
3、make
menuconfig #不做改动即可退出
4、make dep &&
make
三、基本系统的安装:
到此时,busybox和kernel都已经准备完毕,接下来需要一个分区来安装他们。
不管是使用一个单独的分区还是完整的DOM都可以,但总归需要一个完整的目标分区供使用。假设目标分区为/dev/hdc1,下面的说明会以此为基准。
需要说明的一点是,一开始尽量不要用DOM直接调试,因为其速度和容量都十分的不好,会造成调试的困难,直到调试后期再使用是个比较不错的主意。
现在进入基本系统的组装:
#
fdisk /dev/hdc1 and format it with ext2 or ext3. My suggest is ext3.
Mount
/dev/hdc1 /mnt/dom # mount目标分区
mkdir /mnt/dom/boot
mkdir
/mnt/dom/boot/grub
cp (kernelbackup)/bzImage /mnt/dom/boot # copy kernel to
dom
cp (kernelbackup)/initrd.splash /mnt/dom/boot # copy initrd splash to dom
mkdir /mnt/dom/lib
mkdir /mnt/dom/lib/modules
cp (kernelbackup)/2.4.20
/mnt/dom/lib/modules -arf # copy all modules to dom cd (busyboxpath)
make
PREFIX=/mnt/dom install # install busybox to dom
现在,一个基本系统基本安装完毕,接下来是配置问题:
mkdir /mnt/dom/etc # all config here
mkdir /mnt/dom/dev # device
file
mkdir /mnt/dom/mnt
mkdir /mnt/dom/proc
mkdir /mnt/dom/tmp
mkdir
/mnt/dom/var
mkdir /mnt/dom/lib
mkdir /mnt/dom/root # home of
root
mkdir /mnt/dom/usr # X window-manager lib, etc
cp
(busyboxpath)/examples/bootfloppy/etc/* /mnt/dom/etc -arf # base config
cp
/dev/* /mnt/dom/dev -arf # device file. Will cutdown part of
all
下面是加入必需的连接库:
1、ldd
busybox
2、查看busybox使用了哪些连接库,拷贝至目标分区中同样的路径下,一般为/lib
3、再用ldd查看连接库是否还有需要的库文件,如果有同样拷贝到目标分区中
4、重复第三步
5、cp /dev/*
/mnt/dom/dev/ -arf # 后期还会做一些裁减
Grub配置:
# add below to your
grub.conf
title new kernel(2.4.20) # title just, u can modify it
anywhere
root (hd0,0) # root setup
kernel (hd0,0)/boot/bzImage-2.4.20 ro
root=/dev/hda1 vga=791 splash=silent # just.....
initrd
(hd0,0)/boot/initrd.splash # splash that show when booting of
OS
现在可以做一些测试,看看基本系统是否工作正常。执行下面的命令
cd /mnt
mkdir dom
mount
/dev/hdc1 dom # mount it
chroot /mnt/dom
/bin/sh
如果你看到登陆成功的信息就表示基本系统没有什么问题了。
重新启动机器,并选择新的启动选项,看看基本系统是否正常,如果有问题,重新检查前面的步骤是否做的有问题。如果启动正常,那么,基本系统就基本完备,可以继续后面的步骤了。
四、Xfree86的裁减和安装:
基本系统已经正常工作,接下来就是xfree86的裁减和安装,首先切换到目标分区并确定系统处于正常工作状态。
在这里需要说明一下Linux的目录分布和作用情况。首先通过“ls
/”列举一下根分区,大致会有以下目录:
bin boot dev etc home lib mnt opt proc root sbin tmp usr
var
下面逐一说明:
bin: shell的工作目录,比如sh、bash、mount等命令
boot:
kernel、ramdisk文件以及grub(lilo)的存放目录,有的发行版会为此目录单独创建一个分区,以防止系统崩溃的影响。在DOM中是不考虑的。
dev:
所有的设备文件都存放在这里,比如/dev/video0、/dev/hda等。全部设备文件大概要占用400K左右的空间,但似乎全部拷贝过来的话,DOM总是会报空间不足,但实际还是有空间的,原因不明。目前的做法是对设备文件做了一些调整,去除了不需要的部分,参考后面的文件列表。
etc:
Ap配置以及系统配置存放目录
home:普通用户的工作目录根
lib:基本库存放目录
mnt:mount
opt:看情形,目前是用做存放firebird
proc:系统工作所需的目录
root:一般为root的工作目录,可以调换
sbin:常规命令存放目录
tmp:一般为临时目录
usr:所有扩展命令和xfree86,以及window-manager所在目录,是系统最大的一个目录,包含内容最多。对于DOM来说,主要是存放连接库、xfree86、字体、window-manager等。
Var:临时目录,一般在发行版中为存放website文件、安装文件以及一些log信息等,在DOM中只作为临时目录使用
大致的分布情况说明完毕,接下来就是具体的裁减工作了。
实际上,xfree86有一些替代实现,比如freedesktop、fb等,甚至framebuffer也是一个可以考虑的方向,但是由于AP使用了nvidia显卡提供的opengl
1.3接口,导致目前的唯一选择就是xfree86。也许有其他更小的实现,希望能在以后改进。
进入正题,xfree86的主程序实际上就是一个XFree86,位于/usr/X11R6/bin,有的发行版下X是一个指向XFree86的连接,有的却是一个完整的程序,但不管怎么样,Xfree86就是最主要的程序。现在,在目标分区上mount发行版,以便可以拷贝我们所需要的:
cd /mnt
mkdir dist # create mount path of distribute
mount /dev/hda1
dist # /dev/hda1 is root partition of your distribute. Check
it.
现在/mnt/dist就是发行版所在的位置。
mkdir /usr/X11R6
mkdir
/usr/X11R6/bin
mkdir /usr/lib
mkdir /usr/X11R6/lib
创建一些需要的目录。
cp
/mnt/dist/usr/X11R6/bin/XFree86 /usr/X11R6/bin -arf 拷贝xfree86的主程序。
cp
/mnt/dist/usr/bin/ldd /sbin # copy ldd that is used to cutdown
ldd是用来在DOM的环境中做裁减工作的,直接输入ldd看看是否可以运行,如果执行有问题,一般是相关的连接库不全,按照之前的方法复制过来就可以了。
现在,要查看XFree86需要哪些连接库和配置文件,以保证其可以运行起来。
cd /usr/X11R6/bin
ldd
Xfree86
此时会看到很多的连接库,那么就需要把这些库全部从发行版上复制过来,可以直接复制到相对应的目录下,比如/usr/lib/或者/usr/X11R6/lib/下,需要注意的一点是,有些库本身还会需要其他的库,可以一层层的ldd出来,网络中有人做过自动工作的工具,但还是手动裁减比较可靠。全部的库导入完毕后,尝试运行/usr/X11R6/bin/XFree86,会看到一些出错信息,提示/etc/X11/XF86Config不存在,那么就将发行版中的/etc/X11目录全部复制到目标分区中:
cp
/mnt/dist/etc/X11 /etc
-arf
实际上这个目录中不是全部都需要的,某些部分是可以删除的,但我没有具体实验,而且尺寸并不是很大,就全部使用了。
现在再执行/usr/X11R6/bin/XFree86,会提示一些库没有找到,但实际上之前已经全部复制过来了,原因是从shell执行一条命令的时候,命令所需要的库是从以下的途径得到的:
1、搜索/lib
2、搜索/etc/ld.so.cache
之前所复制的库文件大半是放在/usr/lib和/usr/X11R6/lib下的,而且现在的/etc下还没有ld.so.cache文件,要生成这个文件就需要ldconfig这个命令:
cp
/mnt/dist/sbin/ldconfig /sbin
-arf
现在ldconfig是有了,但还需要与之有关的配置文件/etc/ld.so.conf,所以:
vi
/etc/ld.so.conf
/usr/lib
/usr/X11R6/lib
现在执行ldconfig,就会在/etc/下出现一个ld.so.cache。以后如果有新加入的库文件,而且不是存放在/lib/下的,都按照这个步骤来导入。现在,执行/usr/X11R6/bin/XFree86,出现的错误提示为无法打开/var/kdb和/var/log。
这里需要说明配置上的一个修改,cat
/etc/fstab,会看到现在的fstab只有一句话:
none /proc proc defaults 0 0
现在要加入一些新的配置,新的fstab如下:
proc /proc proc defaults 0 0
none /var tmpfs
defaults 0 0
none /tmp tmpfs defaults 0 0
none /dev/pts devpts
gid=5,mode=620 0 0
none /data tmpfs defaults 0
0
现在/var、/tmp和/data都是在内存中了,其中/data是将来mount磁盘的地方,需要手动mkdir出来:
mkdir
/data
现在修改/etc/init.d/rcS:
#! /bin/sh
/bin/mount -a
mkdir
/var/log
mkdir /var/lib
mkdir
/var/lib/xkb
重启DOM,现在应该存在/var/log、/var/lib、/var/xkb目录了,当然这些目录只是存放在内存中,所以需要每次启动时临时创建。
再运行XFree86,应该会看到一个错误的提示,说明还需要opengl的一些连接库,从发行版中复制出来就可以了。
尝试在目标分区中执行/usr/X11R6/bin/XFree86,如果没有进入X界面,需要检查之前的步骤是否有没有做对的地方。
五、Window-Manager的选择安装:
到目前为止,X已经完全移植到DOM中了,但一个包含基本系统和X的系统还不能满足AP的要求,接下来是Window-manager的选择和安装。
kde和gnome是无法安装到DOM中的,尺寸太大,可能的选择包括twm、fluxbox、windowmaker、icewm等,但需要满足以下几个条件:
1、有caption,而且Modal
dialog不能被切到后台,以符合用户的操作习惯
2、X上不能有任何多余的部分,即除了AP,不存在任何UI,如taskbar之类
3、尺寸要小
4、最好不要有system menu和system buttons
经过挑选,最终选择了fluxbox作为DOM的window-manager,尺寸相对其他window
manager要大一些(10M),但是较好的满足了以上条件。
安装过程:
1、下载fluxbox
2、./configure
3、make
4、make
install
5、复制相关文件到DOM的相同目录中
6、测试,如果有问题,重复第一步
等window
manager安装完毕后,一个包含基本系统和window的环境就创建成功了。接下来就是一些附属部件的裁减和安装了。
六、其他部件的裁减和安装:
先切换到发行版。最后定义的数据库引擎为Firebird
1.5,所以先下载firebird 1.5(
http://prdownloads.sourceforge.net/f...-0.i686.tar.gz),然后在发行版上先安装。firebird会安装在/opt目录下,将/opt/firebird复制到目标分区中:
cp
/opt/firebird /mnt/dom/opt -arf
然后修改配置文件:
vi
/mnt/dom/etc/init.d/rcS
#! /bin/sh
/bin/mount -a
mkdir
/var/log
mkdir /var/lib
mkdir
/var/lib/xkb
/opt/firebird/bin/fb_lock_mgr
&
/opt/firebird/bin/fb_inet_server
&
现在切换到目标分区中,会看到进程列表中有一个fb_lock_mgr,这说明firebird已经安装成功。
由于实际的裁减过程中会遇到各种各样的问题,有些方面牵涉太广,以至没有办法单独说明,所以接下来是一些可能会遇到的问题说明:
1、nvidia的驱动需要先在发行版上解开,再执行make
&& make install > install,然后修改install中的目标路径以将相关文件安装到DOM上,比如cp
libGL.so /usr/lib改为cp libGL.so
/mnt/dom/usr/lib。具体操作就不列举了。
2、busybox的mount有问题,不能mount -o
loop,所以cramfs的文件需要用发行版的mount,所以在dom的/mnt/cramfs目录下有一个mount,而/bin也有一个mount
3、为了便于调试,在dom中加入了telnet
server和ftp
client,分别使用的是utelnetd和cmdftp,出处可以通过google搜索
4、grub的安装使用grub-install即可
5、由于firebird等模块至少需要一个root用户,而busybox缺省是没有用户的,所以需要在/etc下复制两个文件:shadow和passwd
6、dhcp
client使用的是udhcpc
7、字体主要和以下目录有关:/usr/lib/gconv、/usr/lib/locale、/usr/X11R6/lib/X11/font和/usr/X11R6/lib/X11/locale(限于redhat,其他发行版会有一些差异,但具体内容是一样的)
8、硬件自检使用的是hwsetup,并对源代码做过一些修改,只保留了audio和network
card的检测,在附件里有原始和修改过的两个版本,可以对比参考
9、web
site功能是用kylix自己实现的,没有使用apache
10、由于dom的空间不足以摊平所有文件,所以/usr下面的文件全部都是以一个cramfs文件的格式出现的,参看后面的文件列表。
七、DOM的最后安装和打包:
cramfs文件的创建:
1、确定目标分区的可运行
2、确定/mnt/dom/usr/目录下的文件完整性
3、mkcramfs
/mnt/usr.cramfs /mnt/dom/usr # make a cramfs file of usr
path
4、保存/mnt/dom下的完整列表,以备将来的修改
5、rm /mnt/dom/usr/* -rf
6、mkdir
/mnt/dom/mnt/cramfs
7、cp /mnt/usr.cramfs /mnt/dom/mnt/cramfs
8、cp
/bin/mount /mnt/dom/mnt/cramfs -arf
9、add
/mnt/dom/etc/init.d/rcS:/mnt/cramfs/mount -o loop -t cramfs
/mnt/cramfs/usr.cramfs
/usr
现在,/mnt/dom目录下就已经是一个除了grub全部都是完整的DOM镜像了。那么最后要将这个镜像导入真实的DOM之中:
mkdir
/mnt/realdom
mount /dev/hdc1 /mnt/realdom # assume /dev/hdc1 is real
dom
cp /mnt/dom/* /mnt/realdom/
-arf
sync
此时DOM中已经有了一个完整的镜像,但还没有grub,那么执行:
grub-install
/dev/hdc1
重新启动,并在BOIS中选择真正的DOM,确认DOM的启动没有问题。重新切换到发行版,开始做DOM的镜像文件:
dd
if=/dev/hdc of=domfs # domfs is image of
dom
保存好这个名字为domfs的镜像文件,这就是一个可安装的包,安装到其他DOM中时,输入:
dd if=domfs
of=/dev/hdc
到目前为止,所有的流程都走了一遍,剩下的就是不断的实践和验证了。
后记:
经过一次完整的裁减过程,很自然的对Linux的整体结构和方式有了很清晰的了解,虽然不能对kernel有深入了解,但是起码为以后kernel方面的学习打下了很好的基础。由于牵涉方面比较多和杂,有些部分只能是实践过后才能知道其中的诀窍,当然大体的过程是一样的。
2004-06-01
cyantree
附录:
DOM文件列表:
略