分类: LINUX
2006-08-04 14:08:13
工作目标:制作一个小的linux系统,使之体积尽可能地少,功能尽可能地简化,以在其上能够运行一个RedHat Linux下编译的可执行程序为限。
工作结果:制成一个U盘上的linux小系统,总共大小为
工作环境:PC机一台,U盘(至少
RedHat Linux 9.0(可以使用vmware虚拟)
工作流程:
每一阶段:配置和编译内核
第二阶段:移植内核到U盘上
第三阶段:裁减文件系统
一、配置和编译内核。
(1)准备linux内核源码,放于目录/usr/src下。这里使用的版本是:linux-
(2)配置内核:在源码所在的目录下,使用命令make menuconfig对内核进行配置。在图形界面下可以使用make xconfig命令开始这项工作。对内核的配置涉及到很多软硬件的选项,网上资料很多,这里不一一累述。但是这里因为工作目标是要做成U盘启动,所以应该增加对USB设备的支持,而且linux把USB存储器当成SCSI设备处理,所以也应增加SCSI支持。编译的时候,必须的功能应该选择y编译进内核,部分功能可以选择M表示以模块加载的形式提供支持。非必要的尽量不要选,以减小目标内核的体积。
配置内核完成后,在退出的时候选择“保存”配置结果。
(3)编译内核:首先需要用make dep命令生成所配置的内核选项中的依赖关系,不过在2.6.*的版本中这一步骤已经不需要显式地进行。如果此前曾在这个源码目录里面进行过内核编译的工作,可以用make clean清除上次编译的结果,以免造成影响。生成内核映象的命令是make bzImage.这一过程用时较长,具体时间取决于所配置的内核选项和计算机的处理速度。结束的时候,会告知生成的内核映象是 ./arch/i386/boot/bzImage文件,这就是这一阶段主要的成果了.除此以外,在当前目录下会生成一个System.map的文件,这是内核中的符号表。
(4)生成模块。一般我们都会把或多或少的内核功能配置为模块支持。所以我们需要用命令make modules生成这些模块。接下来用make modules_install把模块拷贝到指定的目录,也就是/lib/modules/目录下以所编译的内核版本号为文件夹名为目录名的文件里。这里的目录是/lib/modules/
(5)生成initrd文件。RedHat Linux使用了一种称之为initrd的工作方式来阶段化系统的初始化过程。使用mkinitrd initrd-
(6)测试内核。利用现行系统进行测试,看看我们构造的内核是否可用。把上面生成的bzImage、System.map、initrd-
title usb Linux (
root (hd0,0)
kernel /bzImage ro root=LABEL=/
initrd /initrd-
第一行是显示在引导画面上的操作系统名字,第二行是引导盘的标记。第三行指明了内核映象文件和根文件系统所在的设备。最后一行是initrd的文件映象。一般情况下都把bzImage重命名为更有意义的新名字,这里没有进行这一处理,使用原始文件名。
重新启动系统,选择新内核进入系统。如果前面的工作没有错误,则会成功地以新内核启动整个系统(包括文件系统)。可以使用命令uname –r查看内核版本号,以验证当前运行的系统内核是否为我们编译的系统。
二、把内核移植到U盘上。
(1)修改initrd。从U盘引导的时候,需要在initrd里面增加对U盘存储的支持。U盘的初始化比内核执行得慢,所以需要对initrd做如下修改:
mv /boot/initrd-
cd /tmp
gunzip initrd.gz
mkdir /mnt/initrd
mount –o loop initrd /mnt/initrd
编辑/mnt/initrd/linuxrc文件,加入以下内容
echo \'wait 3 seconds.....\'
/bin/sleep 3
通过睡眠三秒的方式等待U盘完成初始化了再继续执行。但是这个时候还没有sleep这个程序可用,所以需要另外将这个程序引入。这里采用busybox来实现。下载busybox源代码,编译生成静态的可执行文件busybox.拷贝到/mnt/initrd/bin/下面,并做如下链接:
ln -s /mnt/initrd/bin/busybox /mnt/initrd/bin/sleep
此外,因为计划使用ext2文件系统而不是ext3文件系统来实现文件系统,所以需要把下面这句mount -o defaults --ro -t ext3 /dev/root /sysroot 修改成为mount -o defaults --ro -t ext2 /dev/root /sysroot。
修改完成之后,恢复initrd。
cd /tmp
umount initrd
gzip -9 initrd
(2)格式化U盘。使用工具fdisk格式化U盘,这里假设只将U盘分成一个区,即sda1,并且设置该分区为可引导的。
(3)将该分区做成ext2文件格式,并且添加标签/。所用命令为:
mke2fs –m 0 /dev/sda1
e2label /dev/sda1 /
(4)挂载该分区:mkdir /mnt/usb
mount /dev/sda1 /mnt/usb
(5)拷贝内核及相关文件到U盘。
在/mnt/usb目录下新建一目录boot,把bzImage、System.map和修改过的initrd文件都拷贝进去。
cp /boot/bzImage /mnt/usb/boot/
cp /boot/System.map /mnt/usb/boot/
cp /tmp/initrd.gz /mnt/usb/boot/initrd.img
新建目录/mnt/usb/lib/modules,把/lib/modules/
(6)安装grub.为了从U盘上引导操作系统,需要在该盘分区上安装grub。
先拷贝必要的文件。在/mnt/usb/boot目录下面,建目录grub,并把系统/boot/grub下的文件拷贝过去,最少需要五个文件:
grub.conf menu.lst splash.xpm.gz stage1 stage2
其中grub.conf是grub引导时的配置文件,需要进行修改。这里只列出修改部分:
default=0
timeout=3
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title usbLinux (
root (hd0,0)
kernel /boot/bzImage ro root=LABEL=/
initrd /boot/initrd.img
下面正式安装grub.
cd
umount /dev/sda1
grub
>>root (hd1,0)
>>setup (hd1)
>>quit
如果前面的工作都正确,grub的安装会成功完成。
(7)测试。重启计算机,设置为可从USB设备引导,插入已经制作好的USB盘,系统可以引导到内核完成,然后死机。
三裁减文件系统
一个完整的RedHat Linux由内核部分和根文件系统组成,内核部分只提供操作系统所提供的软硬件管理的功能,根文件系统则来实现用户需要的功能。一个完整的根文件系统最少应包括如下文件夹:
bin dev lib root tmp var
boot etc initrd lost+found proc sbin usr
可以从无到有地手工制作每个需要的文件,也可以从现有系统中直接拷贝再进行修改。前一工作过于繁复,所以这里采用后一种方法。
为了制作一个完整的根文件系统,将环境恢复到原来的宿主系统,并且把U盘再次挂载到/mnt/usb下。以下依次说明根文件系统根目录下(也即/mnt/usb/)下要创建的文件夹。
(1)bin和sbin:这两个文件夹下都是可执行程序,拷贝现有的可执行文件即可,但是不必都拷贝,否则我们的空间吃不消,而且也没有这个必要。选择哪些取决于系统默认启动哪些服务以及你希望给你的系统提供哪些功能。因为我们打算在目标系统上运行一个在完整的RedHat Linux下的程序,所以使用了比较多的功能。
(2)dev:这个文件夹下是设备文件,可以从系统中拷贝过来,使用参数-dpRa.
console hda2 initrd pts ram2 sda sda3 sdb2 tty0 tty3
hda hda3 null ram0 ram3 sda1 sdb sdb3 tty1 urandom
hda1 initctl ptmx ram1 raw sda2 sdb1 tty tty2 zero
(3)etc:这个文件夹下是系统的配置文件,包括系统初始化时的配置和很多服务的配置。为了避免出错,可以把系统中的原文件都拷贝过来。有些文件需要修改:
fstab:
LABEL=/ / ext2 defaults 1 1
none /dev/pts devpts gid=5,mode=620 0 0
none /proc proc defaults 0 0
如果我们的系统以运行级别3运行(这是绝大多数情况),会运行rc.d/rc3.d/下面的每个脚本文件,其中每个代表一种服务。如果需要关闭某些服务,只须要在这里删除相应的文件即可。不用担心会对系统造成损害,因为这里只是一些链接文件,删除这些链接并不会对系统的完整性造成影响。值得注意的是,这里的每个服务都是用bash脚本实现的,需要用到可执行程序,也就是/bin,/sbin/,/usr/bin,/usr/sbin下的可执行程序。如果这里选取了某种服务,却没有把它所依赖的可执行程序载入,运行时就会出错。
此外,由于这个文件夹下的passwd、shadow、gshadow、gpasswd等文件管理着系统的帐户和组策略,拷贝后的目标系统会拥有和原系统同样的帐户和密码,以及完全一样的组配置。
(4)lib:这一文件夹下包括支持的模块(第二个阶段中已经完成)和运行程序依赖的动态链接库文件。使用ldd 查看每个可执行程序依赖的库,从原系统中拷入即可。
(5)proc:这个文件夹用于存放系统运行时的内核信息,便于用户查看系统运行时信息,不需要添加任何文件。
(6)root:这个文件夹是超级用户登录时的默认根文件夹。只需要把原系统中的几个隐藏配置文件载入即可。
(7)usr:这里需要的文件也依赖于所选取的服务。
(8)var:这里使用了七个文件夹,有些是空的,但是必须。
empty lib lock log run spool tmp
empty:有文件夹sshd,为空。
lib: random-seed
lock: 有文件夹subsys,为空
log : boot.log dmesg lastlog messages secure vbox cron maillog spooler wtmp
spool: cron(空文件夹)
tmp: 空文件夹