Linux 系统裁减指南3

来源:互联网 发布:文思创新软件 编辑:程序博客网 时间:2024/05/19 20:49
5.6 再论initrd
在前面的5.3节中,对initrd机制已经有了比较详细的讨论。准确的说,该部分
内容来自linux-2.4/Documentation/initrd.txt 文件。但是在实践中,我们发现其
中描述的有些方法并不适用。是新版本内核的变化造成的(内核实现与文档不同步
),还是2.4版内核的bug,不得而知。在我查证的过程中,看到网上有不少相关的
问题和讨论。遗憾的是至今我还不能确认到底是什么原因。
后来我又专门读了2.2版内核中所附带的 initrd.txt 文件。我感觉实际的情况
似乎更接近于这个老文档的描述。我还看到一个有关的patch文件,从该文件中可以
明确看到新的initrd.txt文档的改变。下面是该文件的开始部分(行首的-表示老文
档有而新文档中已经删除,+表示新文档中增加的内容)。
Using the initial RAM disk (initrd)
===================================

-Written 1996 by Werner Almesberger <almesber@lrc.epfl.ch> and
- Hans Lermen <lermen@elserv.ffm.fgan.de>
+Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch
> and
+ Hans Lermen <lermen@fgan.de>


-initrd adds the capability to load a RAM disk by the boot loader. T
his
-RAM disk can then be mounted as the root file system and programs c
an be
-run from it. Afterwards, a new root file system can be mounted from
a
-different device. The previous root (from initrd) is then either mo
ved
-to the directory /initrd or it is unmounted.
+initrd provides the capability to load a RAM disk by the boot loade
r.
+This RAM disk can then be mounted as the root file system and progr
ams
+can be run from it. Afterwards, a new root file system can be mount
ed
+from a different device. The previous root (from initrd) is then mo
ved
+to a directory and can be subsequently unmounted.
下面我试图将我遇到的问题和能够确认的东西记录一下。(后面我们分别称新
、老文档为initrd.txt-2000和initrd.txt-1996)
5.6.1 根到底在哪里
在配置使用initrd之前,首先你要清楚,系统正常运行时,根文件系统挂载在
什么设备上(也就是说,root device是什么——root在哪里?)。
我们知道,使用initrd机制的话,系统启动时先以RAM Disk(/dev/ram0)作为
根,然后通过某种方法将根转换到“真实的根(real-root-dev)”(之所以说rea
l,是与前面的RAM里临时的根比较而言)。一种常见的情形是启动时用initrd,然
后切换到一个硬盘分区,比如/dev/hda1。
事实上,这个根转换不是必须的。我们完全可以就把/dev/ram0作为我们真实的
根设备。这时,系统启动之后所有的操作都在RAM Disk中进行。当然这样做也有一
个明显的缺点,即无法保存数据。比如对系统配置进行的修改(象IP地址),重新
启动之后就丢掉了。如果要保存数据,就要想别的办法。
LiPS目前的做法就是这一种(没有根转换,initrd就是真实的根)。为了在重
新启动之后保持配置文件的修改,我们将目录/etc链接到了其他非易失存储器(例
如,一个硬盘分区,或者USB盘的分区)。
指定根设备是通过内核参数“root=”来完成的。以GRUB引导器的配置为例:
kernel /boot/bzImage ro ramdisk_size=65536 root=/dev/ram0
initrd /boot/initrd.img
其中 ramdisk_size=65536 说明初始RAM盘的大小为64MB,root=/dev/ram0 说
明根的位置。下面第二个例子来自一台在hda1安装了Redhat 9的机子:
kernel /boot/vmlinuz-2.4.20-8 ro root=/dev/hda1
initrd /boot/initrd-2.4.20-8.img
很明显,这里 root=/dev/hda1 指定了真实的根,其启动过程包含根的转换。
但是这里没有指定 ramdisk_size,因为initrd的缺省大小是4MB,而initrd-2.4.2
0-8.img比较小,所以用缺省值即可。
(我们多次提到root, root filesystem, root device, 自己体会吧。)
5.6.2 linuxrc
在initrd机制的设计中,初始RAM盘只是作为一个过渡性质的根设备,由/linu
xrc来完成操作环境准备(比如加载一些不常用的、没有编译进内核的驱动程序模块
)和根转换工作。
Linuxrc的执行是自动的,即内核挂载initrd盘作为根,如果根下面有这个文件
(也就是/linuxrc),就执行它。(如果没有呢?当然什么也不做。所以linuxrc也
并不是必不可少的。)
接下来说说linuxrc的内容。下面的例子是从initrd-2.4.20-8.img中释放出来
的:
[root@lips initrd]# cat linuxrc
#!/bin/nash

echo "Loading jbd.o module"
insmod /lib/jbd.o
echo "Loading ext3.o module"
insmod /lib/ext3.o
echo Mounting /proc filesystem
mount -t proc /proc /proc
echo Creating block devices
mkdevices /dev
echo Creating root device
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
echo Mounting root filesystem
mount -o defaults --ro -t ext3 /dev/root /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
该脚本中首先加载了支持ext3文件系统所需的模块,然后挂载真实的根文件系
统,并进行转换。特别需要注意的是,linuxrc脚本一般是用nash解释执行的,而不
是通常的bash。有关nash的详情请看手册页nash(8)。简单说,nash内置实现了多数
在执行linuxrc这个阶段可能用到的命令,比如mount, pivot_root, umount;而如
果使用bash,象mount等都是“外部命令”,就需要复制/bin/mount到initrd映像文
件中。实际上,在initrd-2.4.20-8.img的/bin中只有insmod和nash两个程序(mod
probe符号链接到insmod):
[root@lips initrd]# ls bin/
insmod modprobe nash
当我按照5.3.4节描述的方法测试linuxrc的时候发现,我的脚本头两句执行就
报错。
mount –o ro /dev/hda11 /sysroot
cd /sysroot
这里我的真实的根设备是/dev/hda11,/sysroot是initrd映像中存在的一个目
录。这两句完全是按照该文档的要求写的。后来经过多次试验才发现问题之所在。
第一,nash实现的mount命令语法与我们常用的/bin/mount并不完全兼容;第二,n
ash根本没有实现cd命令。
因此,可以推断initrd.txt-2000中讲linuxrc时所举例子不是用的nash。实际
上在该文档中根本没有指明用什么shell。再回头仔细看才发现,所有例句都是在r
oot的shell命令提示符“#”后面的,那么它用的是bash之类了。但是令人迷惑的是
,同样在该小节中稍后出现如下例句: # exec chroot . what-follows <dev
/console >dev/console 2>&1
为什么用exec执行chroot呢?chroot可以在命令行直接用啊。文档中讲到,wh
at-follows可以是/sbin/init。我用nash试了下面这个句子(nash中用exec执行外
部命令):
exec chroot . /sbin/init <dev/console >dev/console 2>&1
还是不行。错误信息:
Usage: init 0123456SsQqAaBbCcUu
开始我还以为后面那一串是个“magic number”,后来想以Usage开头应该是讲
使用这个命令的语法。看init(8)手册页,果然要求给一个参数,0~6当然是运行级
别啦,试了一个init 3也还是不行。尤其搞不明白后面那些个console什么意思。
5.6.3 根转换机制:新的?旧的?
前面我们多次提到了根的转换。在initrd.txt的两个版本中,分别描述了两种
根转换机制,其中2000版中称1996版的内容已经“过时”,不推荐使用。然而事实
上要麻烦的多,事情并不总是按照预期(如文档所述)运行。
为了弄清楚这个问题,我进行了一系列测试。环境是这样的:
O 使用initrd机制,已经准备好了根文件系统映像文件initrd.img,准备好了内核
bzImage;
O initrd.img的所有内容释放到一个硬盘分区/dev/hda11,ext2文件系统;
O 在/dev/hda11上面增加一个/boot目录,存放bzImage和initrd.img文件;
O 以/dev/ram0作为根启动,然后以某种机制转换到“真实的根”/dev/hda11。
系统的引导器是GRUB,安装在硬盘MBR,grub.conf位于/dev/hda1(也就是做测
试的实际的根文件系统)。按照上述环境配置,在grub.conf中增加如下内容:
title lips (testing ......)
root (hd0,10)
kernel /boot/bzImage ro root=/dev/hda11 ramdisk_size=65536
initrd /boot/initrd.img
下面我们分别使用不同的/linuxrc进行了测试,以确认到底哪种机制是可行的

第一,如果没有/linuxrc会怎么样呢?
结果是系统能够成功启动到以/dev/hda11作为根,并且把initrd(也就是旧根
文件系统)的内容移到了/initrd目录。这是符合initrd.txt-1996文档中第一段的
描述的。所以只要你使用了initrd,指定了新的根,并且准备好了/initrd目录(已
经在/dev/hda11创建了/initrd),内核可以自动完成根的转换工作。终端上面有如
下输出信息:
Trying to move old root to /initrd ... okay
这里有个小问题,即最后/initrd没有卸载,这意味着initrd所分配内存也没有
释放。因此umount /initrd不是内核自动完成的,而应该在/linuxrc中的某个位置
进行。如果linuxrc仅包含卸载/initrd的命令,如下:
#!/sbin/nash
umount /initrd
则执行情况是这样的:umount命令报错(返回错误码22),然后出现前面所示
Trying…的信息。结果跟前面是一样的。因为linuxrc执行在先,当时旧根还没有被
转移到/initrd中来。
如果没有/initrd目录会怎样?我们把/dev/hda11上面的/initrd目录删除,重
新启动(没有/linuxrc),结果是可以启动到以/dev/hda11为根,且看不到原来的
initrd。该过程中出现如下信息:
Trying to move old root to /initrd ... failed
Unmouting old root
Trying to free ramdisk memory ... okey

第二,pivot_root可以用,但是chroot不能用。
pivot_root是在initrd.txt-2000文档中引入的新机制。在测试pivot_root的过
程中,除了在nash中不能用cd命令造成的困惑(这个问题前面已经说明)之外,使
用pivot_root基本上是成功的。/linuxrc脚本的主要内容如下:
#!/sbin/nash
mount -o defaults --ro -t ext2 /dev/hda11 /sysroot
pivot_root /sysroot /sysroot/initrd
但是,用这个脚本不能启动,造成系统挂起:
VFS: Cannot open root device “hda11” or 03:0b
Please append a correct “root=” boot option
Kernel panic: VFS: Unable to mount root fs on 03:0b
如果按照initrd.txt-2000的指导,pivot_root之后应该执行chroot,但是我始
终没有办法使chroot成功执行(有关情况前面已经说明)。不过可以肯定的是,pi
vot_root执行成功之后,当前目录就是新的根目录。
第三,/proc/sys/kernel/real-root-dev
initrd.txt的新版本中最后一节专门指出,向/proc/sys/kernel/real-root-d
ev文件中echo数字的方法(称为change_root机制)是过时的。然而令人迷惑的是,
Redhat 9的缺省安装产生的initrd-2.4.20-8.img中(前面已经列出了其/linuxrc文
件内容),同时使用了pivot_root和change_root机制。
测试下列/linuxrc脚本,系统可以启动到/dev/hda11,但是/initrd没有卸载。
如果在脚本末尾umount /initrd,会返回错误码16。
#!/sbin/nash
mount -t proc /proc /proc
mkrootdev /dev/root
echo 0x0100 > /proc/sys/kernel/real-root-dev
#echo 0x030b > /proc/sys/kernel/real-root-dev
mount -o defaults --ro -t ext2 /dev/hda11 /sysroot
pivot_root /sysroot /sysroot/initrd
umount /initrd/proc
虽然这样可以启动,但是有关real-root-dev还有几个没有弄清楚的问题:
real-root-dev的值到底是什么?
目前我还没有看到解释real-root-dev的值是什么东西的正式文档,根据情况判
断的话,我认为应该是该设备的“major-minor”(主、次设备号)。
为什么用0100而不是030b?
如果上述判断准确的话,那么写入0100就表示/dev/ram0。这就奇怪了,“真实
的根设备”应该是/dev/hda11呀,那么是不是应该写030b呢?但是测试发现用030b
同样会导致不能启动。
Kernel panic: VFS: Unable to mount root fs on 03:0b

5.7 提示
5.7.1 文件系统目录层次结构
根文件系统的目录结构最好符合“Filesystem Hierarchy Standard(文件系统
层次标准)”[7],而不能自己随意创建。
顺便说一下,象这种情况:/bin, /sbin, /usr/bin, /usr/sbin 这4个目录都
可以放应用程序,具体放在哪个目录,则要根据该应用程序在系统中的作用来确定
。一般地,系统的关键应用程序放在/bin,只能给超级用户root访问的关键应用程
序放在/sbin,相比之下比较次要的应用程序和root应用程序分别放在/usr/bin和/
usr/sbin。
5.7.2 mklips.sh(制作LiPS的脚本)
复制文件的工作全部可以手工进行,但是做一个shell脚本来完成所有工作显然
是一个更好的办法。
在我们的项目中,制作LiPS(也就是完成裁减Linux)的工作,除了编译内核之
外,都可以通过mklips.sh脚本完成。
5.7.3 lips.conf(LiPS配置文件)
lips.conf是LiPS的配置文件,由mklips.sh脚本使用,主要用来控制所制作的
LiPS系统包括哪些可选的模块,例如:
INCLUDE_APACHE=no
INCLUDE_IPTABLES=no
INCLUDE_PROFTPD=yes
INCLUDE_NFSD=no
INCLUDE_SAMBA=yes
通过一系列的INCLUDE_?=yes或者no,可以实现LIPS的模块化。在mklips.sh脚
本中,判断每个INCLUDE的值,来确定是否复制某个模块相关的文件。
配置文件中还可以包括其他可配置的信息。
5.7.4 cp –dpR
复制文件请使用“cp –dpR”命令,可以保留文件的属性(特别是对于设备节
点和符号连接等特殊文件),还可以复制整个目录。
5.7.5 如何判断一个程序依赖哪些文件
除了库文件外,关键是找出相关的配置文件。man手册页是判断应用程序配置文
件的重要依据。我们以安装Apache Server为例来说明判断复制哪些文件的过程。
首先确定其可执行文件是/usr/sbin/httpd。然后看httpd的手册页,即
[root@lips lips]# man httpd
httpd(8)
httpd(8)
NAME
httpd - Apache hypertext transfer protocol server
…………(略)
FILES
/etc/httpd/conf/httpd.conf
/etc/mime.types
/etc/httpd/conf/magic
/var/log/httpd/error_log
/var/log/httpd/access_log
/var/run/httpd.pid
February 1997
httpd(8)
(END)
这时关键看最后一段FILES,列出了有关的配置文件、日志文件和进程文件,那
么我们就知道了httpd要在目标系统中运行,这几个配置文件是必不可少的。
把httpd和用ldd找出的库文件以及上述配置文件复制到目标系统,运行httpd试
一下,看看是否正常。一般情况下应该没有问题。但是httpd比较特殊,除了ldd找
出的库文件外,它还需要很多可加载的模块(库)。怎么发现呢?重要的一点是看
出错信息(有时候还要查看日志中的信息,/var/log/messages或者应用程序日志)
,看httpd报告缺少什么;还可以看看相关的配置文件httpd.conf,也能找到有用的
信息。然后我们发现需要/usr/lib/httpd这个目录下的库,把它也复制过去即可。

5.7.6 带库文件复制——lcp()
在复制可执行文件(软件)的过程中,如果没有正确复制相关的库文件,该软
件肯定不能在目标系统中正常运行。而通过ldd命令手工确定每个软件的库文件,是
一个繁琐且费时的任务。另一个隐含的缺陷是,当你不再需要某个软件时,删掉可
执行文件之后,相应的库文件是否需要删除呢?如果删除了,而该库文件是其他软
件也需要的,会导致其他软件不能用;如果不删除,就有可能留一些垃圾库文件在
目标根文件系统中。
因此,最好是能够保证每次复制可执行文件的同时自动复制相关联的库文件。
我写了一个脚本函数 lcp() 来解决这个问题。语法和主要代码如下(以#开头的行
为注释):
# lcp BIN BINPATH LIBPATH
# BIN:可执行文件路径
# BINPATH:可执行文件的目标路径(复制到哪里)
# LIBPATH:相关库文件的目标路径
lcp()
# run()是另一个函数,执行它后面的shell命令,并在遇到错误时报错、写错
误日志
# 首先复制BIN到BINPATH
run "$CP $BIN $BINPATH"
# 使用ldd找出与BIN相关的库文件,把ldd的输出送给LDDSTR
LDDSTR=`ldd $BIN`
# 循环检查LDDSTR字符串的每一项
for STR in $LDDSTR; do
# 判断出库文件路径
LIB=`echo $STR | grep "/lib/" `
if [ -z "$LIB" ]; then
continue
fi
# 复制LIB到LIBPATH,除非要复制的库文件在目标路径中已经存在
LIBNAME=`basename $LIB`
if [ ! -f "$LIBPATH/$LIBNAME" ]; then
run "$CP $LIB $LIBPATH"
run "cp $LIB $LIBPATH"
else
log "Warning: File "$LIBPATH/$LIBNAME" exis
t."
fi
done
}
5.7.7 库文件的命名
(参考资料[9]之6.2节)
我们这里所说的“库”都是指的GNU C Library,也就是glibc。
在/lib下面可以看到很多库文件,主要分为4类:
O 实际的共享库(Actual shared libraries)
文件名格式为 libLIBRARY_NAME-GLIBC_VERSION.so,其中LIBRARY_NAME是库的真正
名称,GLIBC_VERSION是glibc包的版本号。比如glibc 2.2.3版math(数学)库的文
件名为libm-2.2.3.so。
O 主修订版本符号链接(Major revision version symbolic links)
库的主修订版本号与glibc版本号不同。比如,glibc 2.2.3的C共享库libc-2.2.3的
主修订版本号为6,libdl-2.2.3为2。主修订版本符号链接的命名格式为 :libLIB
RARY_NAME.so.MAJOR_REVISION_VERSION,那么C共享库的符号链接即 libc.so.6。
一个程序连接到一个库之后,它在运行时访问的就是这个符号链接。
O 版本无关的符号链接(Version-independent symbolic links to the major re
vision version symbolic links)
这些符号链接的作用是为用到某个库的所有程序提供一个统一的入口,而不管实际
上glibc的版本或者该库的主修订版本。其命名格式为 libLIBRARY_NAME.so。比如
,libm.so链接到libm.so.6,libm.so.6又链接到libm-2.2.3.so。唯一的例外是li
bc.so,是个脚本。连接一个程序时用的是这个符号链接。
O 静态库文件(Static library archives)
这些库是应用程序静态连接用的。格式为 libLIBRARY_NAME.a.




6 引导

6.1 引导过程概述
6.2 几种引导方式
几种引导方式的粗略比较如下表所示。
优点
缺点
DOC
DOM
FLOPPY
HARDDISK
NETWORK
USB-HDD
容量大,读写可靠

6.3 grub引导器
有了前面生成的Linux内核和根文件系统映像文件后,制作引导盘非常简单。在
动手制作引导盘之前,最好先了解一下grub引导器。
Grub是一个通用的多引导加载软件,与较早期多数Linux发行版本提供的另一个
引导器lilo相比,grub的功能更强大、设置更方便、更灵活。因此本项目选用grub
作为引导器软件。
本文档不是grub的教学文档,所以有关grub的详细用法,请参考其他有关文档
。这里仅强调几点:
O 引导盘的文件系统可以是ext2,ext3,msdos (FAT),vfat (FAT32),等等;
O grub表示硬盘、分区的方式与Linux的方式不同。Linux系统的IDE硬盘表示为/de
v/hd{a,b,c,d},SCSI设备表示为/dev/sd{a,b,c,d,…},分区从1开始编号,比如P
rimary Master IDE硬盘的第二个分区是/dev/hda2;而grub的硬盘(包括IDE和SCS
I)统一从0开始编号,分区也是从0开始编号,比如系统中的第一个硬盘是(hd0),
其第一个分区是(hd0,0)。
O 在grub的提示符下面输入命令和参数时,按TAB键可以自动补全。
6.4 USB引导
使用USB引导盘有很多好处,比如说,容量大、读写可靠,不占用IDE接口,携
带方便等等。
6.4.1 制作步骤
6.4.1.1 创建文件系统
首先,必须在USB盘上面创建文件系统(也就是格式化)。你几乎可以使用gru
b支持的所有文件系统,包括常见的各种文件系统,比如ext2,ext3,FAT,FAT32等
。但是根据我的经验,需要注意的是:
O 最好不要使用FAT,即msdos,因为FAT的文件名有“8.3”的限制,所以象“grub
.conf”这种文件名就被截断成了“GRUB.CON”。
O FAT和FAT32都不能表示符号链接文件,虽然有变通的方法,即将文件再复制一份

顺便说一下在Linux下面怎么访问USB盘。
如果系统中没有其他的SCSI设备,那么插在USB 1接口上面的USB盘的设备名为
/dev/sda,其分区为/dev/sda1。依此类推。一般插入USB盘后,窗口中会出现驱动
程序输出的一些信息,其中有sd?的字眼。接下来就跟访问普通的硬盘分区没有什么
两样了。
#mke2fs /dev/sda1
#mount –t ext2 /dev/sda1 /mnt
注意:Redhat 7.3不支持Intel 845系列芯片组的主板。
6.4.1.2 复制文件
按照下面的列表,复制文件(包括目录结构)到USB引导盘:
备注
/boot/
bzImage
或者vmlinuz
initrd.img
/grub/
grub.conf
menu.lst
符号链接
stage1
stage2
6.4.1.3 安装grub
安装grub到USB盘的引导扇区。假设系统有一块IDE硬盘,这时USB盘是grub看到
的第二块“硬盘”,所以表示为(hd1)。
#grub
grub> root (hd1,0)
grub> setup (hd1)
root命令告诉grub,内核文件所在的位置。Setup命令安装grub到hd1的引导扇
区,如果是setup (hd1,0),则安装到第一个分区(即/dev/sda1)。
上述命令序列也可以通过执行脚本完成。
6.4.1.4 用USB盘引导系统
在用新制作的USB引导盘引导之前,还需要确认BIOS的一个设置,即第一个启动
设备应该设置为“USB-HDD”。
OK,插上USB盘,试一试。
6.5 提示
6.5.1 版本问题?
我们的项目开始的时候用Redhat 7.3,但是后来做USB引导盘时发现,我们的环
境不支持USB盘。我想Redhat 7.3应该是支持USB盘的,因为我以前在7.1下面就用过
。那么有可能是主板的问题,i845的芯片组比Redhat 7.3要新,也许是没有该芯片
组的正确驱动。
后来在Redhat 7.3下更新了内核,使用2.4.20版本的Linux内核即可正常支持U
SB盘。
然而还有一个问题,Redhat 7.3的GRUB版本是0.91,在使用中发现,制作USB引
导盘没有问题,但是一旦你改变USB盘的文件(比如复制一个新的文件上去),本来
可以引导的USB盘就不行了。
而Redhat 9.0使用的是GRUB 0.93,就没有上述问题,并且使用USB盘也没有问
题。也就是说,使用Redhat 9就可以了。不过Redhat 9集成的其他很多软件也有变
化,比如Apache升级到了2.0版本,以前的httpd.conf配置文件要修改过之后才能正
常使用;另外quota接口也有变化。
因此改变版本需要一定的代价,究竟使用什么版本应该综合考虑,最好在项目
开始时就做出正确的选择,并保持稳定。




7 远程串口控制台

7.1 概述

7.2 配置方法
7.3 提示
7.4 Linux 远程串口控制台指南
(这是我以前写的一份简单的文档,曾经贴到网上,附在这里供参考)
Linux 远程串口控制台指南

dot <anonymou@163.com>
Dec 27, 2002

2002年圣诞节期间,我在 Redhat Linux 7.0 (kernel 2.2.16-22) 平台上配置
了远程串口终端,整个过程基本顺利,但是也经历了一些意想不到的波折,幸好最
终是成功了的。乘着记忆还比较清晰的时候,写下这篇文档,以供自己和他人参考


首先参考 "Linux-Remote-Serial-Console-HOWTO",该文档已经足够详尽,按
要求一步步地做即可。该文档描述的是 Redhat 7.2 平台,个别地方跟 7.0 有些差
异,不过问题不大。

要注意的问题主要是:

* 串口直连电缆

开始我并没有在意这个问题,我手头上有一根以前做的直连电缆,是只用了3根
线的那种(2、3交叉,5对接),因此 HOWTO 文档中讲电缆制作的章节我就跳过去
了,没有仔细看,以为我这根电缆就可以了。事实也给人以这种假相:当我按照文
档的说明完成了配置文件的修改,重新引导 Linux 机子,这时在 Windows 的超级
终端中确实显示了所有该显示的信息,看起来没问题。然而接下来配置 getty 时就
不行了,应该出现在超级终端中的 login: 提示符死活不肯出现。以为是 getty 软
件的问题,先后测试了 getty 和 mgetty,都不行。后来在 quickmouce 的提醒下
,又仔细看文档,按照 11.3 节的图 11-1 重新制作了串口直连电缆,才解决问题


* getty 软件

HOWTO 文档中已经指出,mingetty 不支持串口终端,所以这个软件要首先排除
(mingetty 的手册页中也有相关说明)。而 Redhat 缺省安装的就是这个软件,所
以要重新下载安装其他的 getty 类软件。文档中也已经列出了几种常用的 getty
的变种。

来说说 mgetty 先。为什么我先使用了这个软件呢,一是因为 Redhat 7.0 的
安装盘上面有它的 RPM 包,直接拿来装很方便,另外是因为 mingetty 的手册页中
推荐使用 mgetty 。结果是 mgetty 运行后在日志文件中报告大量错误,莫名其妙
。我想可能是这个光盘上的版本老了,于是上网下载了比较新的版本 mgetty-1.1.
25-5.i386.rpm ,运行之后情况好多了,似乎要成功的样子。在没有使用新的串口
线之前,login: 出不来,但是在超级终端中敲的字符 mgetty 可以收到(从日志中
看的出来);换了新制作的串口线之后,第一次!成功了,一切都象预期的那样,
我可以从超级终端登录。可是当我退出想再登录一次,就不行了,甚至我把两台机
子全部重启也不行啦。我又试用 Linux 的 minicom 终端来连接,也是只成功了一
次,就再也不行了。真是怪哉,脑袋都快想破了,也不知道是为什么。后来终于怀
疑 mgetty 有问题,换了其他的,天哪,终于解脱了。不知道后面更新的版本是否
可以,我是没有劲去试了。

再来说说 agetty 。其实没有什么好说的,因为我根本没有用过这个。我本来
想试一下的,但是从网上下载安装太麻烦了。下载了 agetty-2.11w-2.i386.rpm ,
安装时 RPM 说要先安装 login 包,然后又要求什么 pam 包,然后又需要 awk ,
真是 faint 了,太麻烦了,所以最终我也没有安装它。

最后说 getty 啦。也就是 HOWTO 文档中所谓的 “传统” getty 。我下载的
RPM 包的名字叫 getty_ps-2.0.7j-9.i386.rpm 。当我正在为 mgetty 的问题头疼
的时候,换成它之后就一切 OK 了。

* 终端软件

Windows 下面可以用超级终端、NetTerm,Linux 下面有 Minicom 。都比较好
用,注意参数配置与目标机的串口一致。

* 修改过的配置文件列表

/etc/lilo.conf
/etc/inittab
/etc/gettydefs
/etc/securetty
/etc/makedev.d/linux-2.2.x
/etc/security/console.perms
/etc/sysconfig/init
/etc/sysconfig/kudzu

* 再谈串口直连电缆

这次调试在串口直连电缆上面花费了不少力气,对它们的了解也增加了不少。
以前以为直连电缆就是接 3 根线,其实不然。只用了 2、3、5 引脚的直连电缆不
能提供握手信号,因此如果软件需要使用 CTS/RTS 或者 DTR/DSR 流控,就需要连
接更多的引脚。

PC DB9 DB9
-------------------- -----------------------
RxD Receive Data 2 <----- 3 TxD Transmit Data
TxD Transmit Data 3 -----> 2 RxD Receive Data
|--> 6 DSR Data Set Ready
DTR Data Terminal Ready 4 --|--> 1 DCD Carrier Detect
GND Signal Ground 5 ------ 5 GND Signal Ground
DCD Carrier Detect 1 <--|
DSR Data Set Ready 6 <--|-- 4 DTR Data Terminal Ready
RTS Request To Send 7 -----> 8 CTS Clear To Send
CTS Clear To Send 8 <----- 7 RTS Request To Send
RI Ring Indicator 9 (not used)

上面是两端都是 DB9 接头的标准 NULL MODEM 电缆的接线图,可以提供全部握
手信号。这也是 Remote-Serial-Console-HOWTO 中要求的直连电缆做法。我做通串
口控制台使用的就是这种电缆。

如果你打算自己制作电缆,就会发现一些问题。我们一般利用网线(双绞线)
来做,这种双绞线是 8 芯的,而按照图示的连接方法则需要 9 根线。因此最简单
的方法是用那种很多芯的排线来做,需要多少根割多少根(最好是彩色的,不容易
弄混)。后来我想,我们用到的其实就是 CTS/RTS 流控信号,到 2000 年为止 Li
nux 还不支持 DTR/DSR 流控,应该用不了这么多线。于是我就用网线做了根不完整
的直连电缆:2、3 交叉,5 对接,7、8 交叉,还空 3 根线,就把 1、4 也交叉连
上了,结果是用了 7 根线,还空 1 根,与上面比只是少了 4、6 交叉,也就是没
有 DTR/DSR 信号。事实证明这样也是通的。我猜想 1、4 交叉不要应该也是通的,
只是没有试过,已经焊上去懒得再弄了。

关于串口方面的更多内容可以参考 "Linux-Text-Terminal-HOWTO" 和 "Linux
-Serial-HOWTO" 文档。

* 为什么要用串口终端(控制台)?

为什么费劲做这个 Serial Console 呢?最容易想到的理由是省钱,呵呵,省
掉了显卡、显示器、键盘,只剩下一个 "Box",多好玩。

说正经的,这种做法在嵌入式系统的开发中也是很有价值的。现在很多人都在
利用 X86 平台做嵌入式系统开发,甚至做产品。我曾经测试过清华某某做的 foob
ar 服务器,镜像光盘用的,卖给你的就是一个主机,我自己给接上显示器、键盘,
开机就是 Linux ,还可以进入单用户模式,两分钟就把 root 口令改了,你说这样
的服务器有什么安全性可言?如果能够屏蔽本地控制台,配置串口终端,不是更“
象”一个产品吗?
(完)




8 系统安装光盘

8.1 概述
本节介绍一种系统安装光盘的制作方法。安装光盘用于产品阶段的生产安装。
因此该安装光盘必须是可引导的、简单好用,并且一般不包含源代码。
制作可引导光盘的方法有很多种,我们用了一种最简单的方法,就是拿来一个
可引导光盘的ISO映像,然后做必要的修改以满足我们的要求。
请准备Redhat 9的第一张安装光盘,我们将要用到的文件是 /images/boot.is
o。(其他发行版本应该也可以,只要原理是一样的。)
另外如果你的工作平台是Windows,请准备WinISO 5.3软件,用来编辑光盘ISO
映像文件。
当然如果你要烧盘测试的话,还要准备刻录机和CD-RW或者CD-R光盘。
8.2 boot.iso光盘的文件结构分析
用WinISO打开boot.iso即可看到该光盘的文件(其实Redhat 9第一张安装光盘
的/isolinux目录就是boot.iso解开后的内容)。下面是文件列表:
[xmdong@lips isolinux]$ ls
boot.cat initrd.img options.msg snake.msg vmlinuz
boot.msg isolinux.bin param.msg splash.lss
general.msg isolinux.cfg rescue.msg TRANS.TBL
其中关键的文件是boot.cat,initrd.img,isolinux.bin,isolinux.cfg和vm
linuz;isolinux.cfg是如何引导的配置文件,我们主要修改这个文件即可;initr
d.img和vmlinuz分别是初始化RAM盘和内核,其作用在前面章节中已经详细描述过;
另外两个文件是光盘引导需要的,不动它。
其余的*.msg文件是一些引导过程中可能会显示的文本信息,可以不管;splas
h.lss是引导时显示的一个图片,也可以不管。
下面来看看isolinux.cfg的内容。
default linux
prompt 1
timeout 600
display boot.msg
F1 boot.msg
F2 options.msg
F3 general.msg
F4 param.msg
F5 rescue.msg
F7 snake.msg
label linux
kernel vmlinuz
append initrd=initrd.img
label text
kernel vmlinuz
append initrd=initrd.img text
label expert
kernel vmlinuz
append expert initrd=initrd.img
label ks
kernel vmlinuz
append ks initrd=initrd.img
label lowres
kernel vmlinuz
append initrd=initrd.img lowres
这个配置文件的语法结构跟其他引导器的配置文件,比如grub.conf或者lilo.
conf,非常类似,比较好懂。如果再对照光盘引导安装Redhat的实际过程看一下,
基本上不需要什么解释就可以理解。其中以label开头的每个小节是一种引导配置,
缺省(或者timeout后)以label linux引导。每个配置的第一句,kernel指定引导
所用的内核,第二句append指定内核引导参数(主要说明initrd文件的位置,以及
其他参数)。
8.3 制作步骤
1) 复制boot.iso,用WinISO打开;
2) 解放出isolinux.cfg文件,并从光盘映像中删除之;
3) 修改配置文件isolinux.cfg;
4) 制作bzImage和initrd.img,这两个文件用于光盘引导至一个比较正常的Linux系
统下,包括常用的工具软件和服务,我们要在这个环境下进行产品的安装;
5) 将修改后的isolinux.cfg以及initrd.img,bzImage加入光盘;
6) 准备一个setup目录,将产品安装需要的文件和脚本放在这个位置,然后将setu
p目录加入光盘;
7) 删除没有用到的文件,也可以不管,除非加入文件时遇到冲突,必须先把原来光
盘上的文件删除或者改名;
8) 存盘退出,刻录光盘。
下面是一个修改后的isolinux.cfg配置文件的例子,很简单:
default linux
prompt 1
timeout 600
label linux
kernel bzImage
append initrd=initrd.img ramdisk_size=65536 root=/dev/ram0


9 源代码(配置文件和脚本)
9.1 lips.conf
9.2 mklips.sh

??
??
??
??
National Storage System Lab. 
原创粉丝点击