Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,长修远,我们不能没有钱
随笔 - 172, 文章 - 0, 评论 - 257, 引用 - 0
数据加载中……

关于Linux裁剪(转载老鸨在Linuxsir发布的文章)

项目基本结束,这个是其中系统裁减的一个总结文档,不知道有没有人感兴趣:)

=============================================

前言:
为了完成用户的需求,需制作一个完整的环境供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文件列表:

posted on 2007-11-09 11:32 Khan 阅读(3950) 评论(0)  编辑 收藏 引用 所属分类: 周边技术


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理