分类: LINUX
2007-07-28 18:08:02
2001 年 9 月 01 日
这是一个向用户介绍如何构造Linux的图形化安装程序的专栏。介绍的内容包括:安装环境的定制,图形化启动,本地化支持,分区功能,如何支持reiserfs、raid、lvm,rpm包的安装,定制各种启动配置脚本等等。本文是这个系列文章的第一篇,主要是向您介绍如何定制系统安装环境,包括生成安装内核,初始Ram盘的生成,最小化安装环境的定制。
自从Caldera推出了第一个Linux系统下的图形化安装程序以来,现在的主流Linux发布大多都使用图形化的安装程序进行系统环境的安装,比如RedHat的安装程序anaconda,Suse的安装程序yast2,Caldera的安装程序lizard,以及Mandrake的安装程序gi。
这些主流厂商的安装程序都有一个共同的特点,就是它们都是先构造一个完备的最小化的Linux运行环境,定制Linux的启动过程,使得系统内核启动后,加载一个系统装载程序,这个程序将定制好的Linux运行环境部分或者全部加载进入内存,然后将控制转移到图形化安装程序。最后再由此程序启动的图形环境(XFree86),设置对应的语言环境,启动对应的系统安装过程。
的安装程序lizard是Linux世界的第一个图形化安装程序,它的全部程序使用c++语言编制,图形化的风格是基于kde和qt的。值得一提的是,caldera在定制图形化安装时,修改了内核,实现了内核的图形化启动,同时其安装程序的硬件检测功能很强大,可以检测到部分非即插即用的isa设备,而且还提供了类似html风格的帮助系统。因为安装程序要求精炼的环境,而此时通用的XWindows窗口管理器是无法满足需求的(太大而且占用资源太多),所以caldera中还提供了一个最小化的窗口管理器lwm。在caldera安装系统包的过程中,您还可以玩吃豆子游戏,这也是lizard的一大创意。
的安装程序anaconda可能是大家最熟悉的安装程序之一。它的全部程序都是由Python完成。Python是一种面向对象的脚本语言,您可以在 获得它的相关资料。Redhat使用Python Gtk作为图形界面的开发工具。在您解开anaconda的源码包之后,您会发现一个anaconda的文件,这是程序执行的主文件。它提供了一个最小化的slang库以支持文本方式的安装。Redhat的安装程序最大的特点就是很稳健,支持的驱动程序较多,对硬件的支持很强(这说明Redhat安装内核定制得非常好,而且得到了相当多的厂商支持)。但是Redhat安装程序的功能不是特别强,比如对于reiserfs、lvm不提供支持,不支持中文安装(7.2可能会推出中文版)。也有很多厂商的安装程序是稍微修改了RedHat源码构成的,比如VALinux、中科红旗等。
对于Mandrake的安装程序gi,它的全部程序都是使用Perl编制,您可以从 的 上下载最新的安装程序。Perl是一种功能强大的脚本语言,可以非常方便的处理Linux上的各种配置脚本,它的图形界面使用Perl-GTK编制。Mandrake的安装程序是第一种提供中文安装的主流发布。它的安装程序的特点是新,支持的功能相当多,包括配置复杂的文件系统,支持无线通讯设备,多种打印机支持等等。
Redhat和Mandrake的安装程序都是由脚本构成的,它们虽然速度稍慢,但是其构成的安装程序一般都比较稳定,而且便于移植到其他平台上。Redhat的整个安装环境是保存在一个stage2.img的文件里。您可用命令:
mount -o loop stage2.img /mnt/tmp |
将其挂接到指定的目录下,察看Redhat安装程序的结构。Mandrake的安装环境保存在mdkinst的目录下。
一个图形化的安装环境实际上就是一个最小化的Linux运行环境。一般由如下几部分构成:Linux系统安装内核,Linux系统的初始Ram磁盘,系统运行所需的一些shell命令和程序所必需的系统库,初始化程序,系统运行时必须的外部命令,XFree86子系统,字体集和本地化的环境设置,系统的桌面风格和贴图,键盘映射,设备配置数据库,系统安装程序等部分。
系统内核vmlinuz存在系统的启动映像之中,在系统启动时调入,然后Linux调入初始Ram磁盘,由此Ram磁盘上的程序加载运行安装程序的第一阶段加载程序。这是个可执行程序,它一般执行加载硬盘驱动模块,将磁盘上的整个安装环境调入内存,并作为根分区挂接。
这时就有一个在内存中的最小化的Linux系统了,一段映像程序结束运行,释放自己所占的内存,并将控制转移到真正的系统安装程序。这时系统安装程序开始启动XFree86子系统,设置正确的本地化环境,包括本地化环境变量,字体集,正确的键盘映射等,这时就允许用户进行交互,从而在用户的干预下,完成整个系统的安装过程。
一个好的安装程序内核是和安装程序紧密相关的,它必须是完备的和精简的。完备的内核是指:如果安装程序要对某方面的功能进行支持的话,必须在内核中也提供相应的支持。精简的内核是指:对于安装程序不需要的功能,内核一定不要支持,而且能作为模块存在的,就一定要把它设置为模块。这样定制出来的内核很小,保证了定制的内核以及必须的硬盘驱动模块能放入启动映像中。
例如,对于2.4.3内核一组选项是:(在下面的一组选项中没有注明的选项,可以在定制安装程序的内核时省略)
Loadable module support 可加载模块支持 [*] Enable loadable module support 将可加载模块支持打入内核 [*] Kernel module loader 将内核模块加载器打入内核 Processor type and features 内核支持的处理器类型 (386) Processor family 选择386兼容方式编译内核 |
General setup 一般选项 [*] Networking support 内核级网络支持 [*] PCI support 内核级PCI总线支持 (Any) PCI access mode PCI硬件的存取方式 [*] EISA support 内核级EISA总线支持 [*] Support for hot-pluggable devices 支持热插拔设备 [*] System V IPC SystemV的进程间通讯机制 (ELF) Kernel core (/proc/kcore) format 内核文件格式为ELF |
Parallel port support 并行端口支持,要引入并口设备支持时 |
Plug and Play configuration |
Block devices 引入对块设备的支持 <*> RAM disk support 核心支持RAM磁盘 (4096) Default RAM disk size [*] Initial RAM disk (initrd) support |
Multi-device support (RAID and LVM) [*] Multiple devices driver support (RAID and LVM) <*> RAID support 将设备模块md.o打入内核 如果将md.o不置入内核,仅为模块方式,raid分区将无法作为根分区启动系统。这主要是因为raid设备需要在启动之初对硬盘进行读写,以决定raid分区的位置,类型等参数。 |
Networking options |
SCSI support
支持的SCSI设备全部作为内核模块。这些模块将压缩以后存入初始内存映像,以便在使用SCSI控制器时,系统能够插入正确的设备驱动模块。
Network device support
[*] Network device support
对网络设备包括ARCnet、Appletalk devices、Ethernet、PPP、SLIP、Token Ring等类型的设备提供支持,这些设备的驱动程序都可作为设备模块。
ISDN subsystem |
Old CD-ROM drivers (not SCSI, not IDE) [*] Support non-SCSI/IDE/ATAPI CDROM drivers |
Input core support |
Character devices [*] Virtual terminal 允许您在一个虚拟终端上运行几个虚拟中断,可以使用Alt-<功能键>进行切换 [*] Support for console on virtual terminal 设置一个虚拟终端作为系统控制台 |
File systems |
Native Language Support作为模块
这样的选项使得定制的内核支持/proc,ext2和/dev/pts文件系统,可以使用插入模块的方式支持fat、vfat、ntfs、cdrom、reiserfs、rom文件系统。支持NFS文件系统,并能支持内核级的自动挂接。同时,在挂接文件系统时提供本地语言支持,缺省值为iso8859-1。
Console drivers [*] VGA text console [*] Video mode selection support |
Sound |
USB support |
由于在定制安装程序的内核时,要求内核很小,而另一方面安装程序又要支持尽可能多的硬件设备。为了支持尽可能多的硬件,尤其是特殊的存储设备,我们需要在定制初始的启动镜像时将需要支持的部分,如常见的SCSI控制器和非标准的IDE控制器的驱动程序模块放入其中。这样才能够使内核在尝试使用硬盘或其他存储设备时,其设备驱动程序已经提前加载了。
在内核调入内存之后,如果存在内存初始镜像(initrd),那么控制会转到其上并执行配置脚本linuxrc。内存的初始镜像使引导加载器加载一个RAM盘,此RAM盘可以作为根文件系统挂接并且能在其上运行应用程序。此后,新的根文件系统能从不同的设备上挂接(比如光驱或者硬盘)。在挂接了新的文件系统之后,作为根分区的内存初始镜像将成为目录/initrd或者被卸装。
内存初始镜像(initrd)的使用将使得系统的引导过程分成两个阶段,初始启动的内核只需保留最精简的驱动程序最小集,当启动必须加载附加的驱动模块时再由内存初始镜像加载。比如,您在使用了软件RAID方式管理硬盘并使用RAID 1类型的分区作为系统的根分区之后,就必须创建内存初始镜像。这时的内存初始镜像中包含了设备模块raid1.o以及系统命令insmod,和一个shell脚本linuxrc,其内容一定包含:
insmod raid1.o |
在使用内存初始镜像时,系统引导过程如下:
创建一个初始内存镜像实际上就是创建一个文件,这个文件上包含了一个ext2文件系统,它可以使用回环方式(loop)挂接到本地文件系统上。下面的shell程序段可以创建初始内存镜像:
dd if=/dev/zero of=/tmp/initrd bs=1k count=2000 创建一个2000k的整块文件,一定不能有碎片 mke2fs /tmp/initrd 创建一个ext2文件系统 mount -t ext2 /tmp/initrd /mnt -o loop 将此文件作为回环文件系统挂接到/mnt目录下 创建所需的路径和文件: mkdir /mnt/dev mknod /mnt/dev/tty1 c 4 1 mkdir /mnt/lib cp raid1.o /mnt/lib/ mkdir /mnt/sbin cp /sbin/insmod /mnt/sbin/ cp /sbin/ash /mnt/sbin/ ... ... umount /mnt 卸载此文件系统 gzip -9 /tmp/initrd cp -f /tmp/initrd.gz /boot/initrd.img rm -f /tmp/initrd.gz 这样一个内存映像文件就生成了。 |
缺省条件下,内核的标准设置指定了根设备,另外还可以由rdev设置,或者由命令行传递参数root=xxx指定。在initrd环境下也可以改变根设备。首先,系统要挂接/proc,然后使下列文件可用:
/proc/sys/kernel/real-root-dev /proc/sys/kernel/nfs-root-name /proc/sys/kernel/nfs-root-addrs real-root-dev能通过向其写入新的根文件系统设备号来改变,例如 # echo 0x301 >/proc/sys/kernel/real-root-dev |
总而言之,创建初始内存映像文件的主要目的是为了在系统安装(启动)时配置内核模块。这时整个安装过程的最初阶段会按如下方式工作:
安装程序的运行环境是整个安装过程第二阶段,它是在内核以及初始内存映像运行之后,由第一阶段的安装程序装入内存的。在此之后,安装程序才正式从其上开始运行。定制最小化的安装程序运行环境也就是定制最小化的Linux系统运行环境。
定制怎样的安装程序运行环境和安装程序所提供的功能密切相关。一般而言,安装程序都要打开多个控制终端,所以为了便于调试,安装环境中应该具备完整的shell命令环境。同时,为了支持图形化显示,那么安装环境还需要XFree86系统,Gtk(Qt)库环境,可能还需要gtk-engine以支持贴图的显示方式。而对于要提供多语言支持的安装程序,这就需要提供glibc的本地化环境,多种字体集,不同的键盘映射方式。另外对于安装程序提供支持的硬件设备,也应该将其驱动程序模块放入安装程序的运行环境中。
安装程序运行环境一般应包括如下内容:
为了使运行环境最小,构建安装程序运行时刻库时,必须也是最精简的,也就是说,每个库文件必须被至少一个命令或者安装程序的某个部分所使用。同时在拷贝的过程中,使用strip命令拨去所有的调试信息。要检查一个命令使用了哪些动态库可以使用命令ldd。
例如,当安装程序中包含fdisk命令时,要检查它所需要的运行库,只需要运行下面的命令:
ldd `which fdisk` |
这样我们就可以知道,fdisk需要的动态库为libc.so.6和ld-linux.so.2。接下来的工作就是将这两个库拷贝到安装程序的运行环境,同时运行
strip libc.so.6 strip ld-linux.so.2 |
下面我们以Mandrake 8.0为例,让我们看看它的安装程序运行环境包含了些什么东西。Mandrake 8.0的安装程序存放在光盘目录mdkinst下,其安装程序的目录结构是:
/etc
包含pcmcia设备的配置选项,sysconfig目录,调色板,Imlib缺生设置。
/lib
包含系统的运行库lib*和支持的驱动程序模块集。
/usr/X11R6/bin
包含XFree86服务器,包括XF86_FBDev、XF86_VGA16。
/usr/X11R6/X11
包含XFree86服务器的字体和本地化环境。
/usr/bin/
这是整个安装程序最关键的目录,它包含安装程序执行时需要的系统命令,安装程序源码,install2文件为安装程序的主控文件,所有安装程序的源程序保存在perl-install目录下。
/usr/lib/
包含多语言支持的运行库保存在gconv目录下,perl5运行所需的模块保存在perl5目录下,其他与本地化和gtk相关的设置。
/usr/share
包含控制台字体保存在consolefonts下,程序贴图和桌面主题贴图一部分保存在gtk目录下同时也包括此目录下的所有*.xpm,*.png文件,glibc的本地化环境保存在locale目录下,键盘映射分别保存在keymaps和xmodmap目录下,检测设备的信息文件(包含设备标识与设备驱动程序的对应关系)保存在ldetect-lst目录下。
保存在/lib/目录下的系统运行时刻库:
系统RPM包 | 动态库 |
Glibc | Ld-linux.so.2,libc.so.6,libcrypt.so.1,libdl.so.2,libm.so.6,libnsl.so.1,libnss_dns.so.2,libnss_files.so.2,libnss_nis.so.2,libresolv.so.2 |
libext2fs2 | libcom_err.so.2,libe2p,libuuid.so.1 |
db3 | libdb-3.1.so |
db3-devel | libdb.so.2 |
zlib1 | Libz.so.1 |
libpng2 | libpng.so.2 |
libgtk+1.2-devel | libgtk-1.2.so.0,libgdk-1.2.so.0 |
libimlib1 | libgdk_imlib.so.1 |
libglib1.2 | libglib-1.2.so.0 |
libglib1.2-devel | libgmodule-1.2.so.0 |
libbzip2_1 | libbz2.so.1 |
Lvm | liblvm.so |
Rpm | librpm.so.0,librpmio.so.0 |
XFree86-devel | LibX11.so.6,libXext.so.6 |
XFree86-libs | libXi.so.6 |
XFree86-server-common | libfont.so.1 |
Freetype | libttf.so.2 |
保存在/usr/bin/目录下系统支持的命令:
系统rpm包 | 系统命令 |
Ash | Ash |
console-tools | Consolechars |
Cpio | Cpio |
Gzip | Gzip |
e2fsprogs | badblocks,mke2fs,resize2fs,dumpe2fs |
util-linux | fdisk,rescuept |
Modutils | insmod_,rmmod |
Raidtools | mkraid,raidstart, |
bzip2 | bzip2 |
Rpmtools | packdrake,parsehdlist |
perl-base | Perl |
Lvm | pvcreate,pvdisplay,vgchange,vgcreate,vgdisplay,vgextend,vgremove,vgscan,lvcreate,lvdisplay,lvremove |
kernel-pcmcia-cs | Ifport |
Dosfstools | Mkdosfs |
reiserfs-utils | mkreiserfs,resize_reiserfs |
另外,因为perl语言具有一部分系统功能,所以为了减小运行环境,部分命令还可以采用perl语言编制。这些命令包括: basename,bug,cat,chmod,chown,cp,dd,df,dirname,displaySize,dmesg,du,e2fsck,fsck.ext2,getopts,grep,gunzip,head,head_tail,header,hexdump,insmod,kill,ln,loadkeys,ls,lsmod,lspci,mkdir,mknod,mkswap,modprobe,more,mount,pack,ps,raidstop,report_bug,rights,rm,rmdir,route,sh,sort,strings,swapoff,swapon,sync,tail,tr,true,umount,uncpio,unpack,which
于辰涛,联想(北京)电脑公司软件工程师。目前主要从事Linux系统安装程序的开发工作,主要研究兴趣是操作系统的工作机制和开发底层系统程序。您可以通过电子邮件 scu_yct@263.net 跟他联系。 |