摘要:虽然经常安装操作系统,但你有没有想过,操作系统安装的时候都做了哪些工作?系统安装的本质是什么?在操作系统安装之前,系统是怎么从裸机上起来的?等等问题。本文主要以Centos系列的linux为例,向你详细解释操作系统安装的详细过程,引导程序,系统内核,livecd,installer等的区别和联系。本文主要为你解答这些问题
[huangyk@huangyk CentosInstall]$ ls CentOS_BuildTag EULA images Packages repodata RPM-GPG-KEY-CentOS-Debug-6 RPM-GPG-KEY-CentOS-Testing-6 EFI GPL isolinux RELEASE-NOTES-en-US.html RPM-GPG-KEY-CentOS-6 RPM-GPG-KEY-CentOS-Security-6 TRANS.TBL
isolinux目录的内容:
-r--r--r--. 1 root root 2048 7月 6 2012 boot.cat -r--r--r--. 2 root root 84 7月 6 2012 boot.msg -r--r--r--. 2 root root 334 7月 6 2012 grub.conf -r--r--r--. 4 root root 31596586 7月 6 2012 initrd.img -r--r--r--. 2 root root 24576 7月 6 2012 isolinux.bin -r--r--r--. 2 root root 936 7月 6 2012 isolinux.cfg -r--r--r--. 2 root root 165080 7月 6 2012 memtest -r--r--r--. 2 root root 151230 7月 6 2012 splash.jpg -r--r--r--. 1 root root 2215 7月 6 2012 TRANS.TBL -r--r--r--. 2 root root 162860 7月 6 2012 vesamenu.c32 -r-xr-xr-x. 4 root root 3986608 7月 6 2012 vmlinuz其中,isolinux.bin引导程序,负责将操作系统内核加载到内存,isolinux.cfg是isolinux.bin将会读取的配置文件
grub.conf是grub读取的配置文件,grub也是引导程序
mmtest和vmlinuz等是可以启动的系统内核,initrd.img是初始化所用的磁盘镜像,里面包含一个最小化的系统,包含了/dev,/etc,/bin等很多基本的目录,还有关键的init程序,负责驱动的加载和文件系统的初始化。
images目录的内容:
-r--r--r--. 2 root root 372736 7月 6 2012 efiboot.img -r--r--r--. 2 root root 35997696 7月 6 2012 efidisk.img -r--r--r--. 2 root root 136585216 7月 6 2012 install.img dr-xr-xr-x. 2 root root 2048 7月 6 2012 pxeboot -r--r--r--. 1 root root 888 7月 6 2012 TRANS.TBL其中,最重要的是引导第二阶段安装需要用到的镜像文件install.img(rhel 5中是stage2.img),anaconda程序就在这个镜像文件中。
另外,如果想详细的了解安装文件中每个文件的作用,可以参考这里:http://blog.csdn.net/trochiluses/article/details/11774165
先用file命令查看install.img的文件系统类型,可知是suqashfs,用mount -o loop -t squashfs install.img ./img/的方式挂载出来。内容如下:
etc firmware lib lib64 modules proc usr var由此可见,这也基本上是文件系统中重要文件的磁盘镜像:
除了主执行体/usr/bin/anaconda,其它安装脚本模块均在/usr/lib/anaconda主目录下。我们看一下整个anaconda主目录的结构:
/usr/bin/anaconda: 主程序,是python脚本。
/usr/lib/anaconda/installclasses:定义了在安装过程中用户可选择的安装类型。每个安装类型描述文件根据相应安装类型的特点,分别对安装步骤、分区策略以及安装包的取舍给出了不同的方案。里面有两个文件fedora.py和rhel.py,分别针对fedora和rhel的安装类型。其他的Linux发行版可以定义它们自己的安装类型。
/usr/lib/anaconda/iw:图形安装模式的模块。包含所有图形界面类所在的模块,每个图形界面对应一个类,负责相应安装步骤图形界面的具体外观显示及与用户的交互,(可能)调用anaconda主目录下的相关安装行为模块完成具体的安装操作。
/usr/lib/anaconda/storage:存储配置的响应目录(如分区,FCOE, iSCSI, RAID, ZFCP的配置等)。
/usr/lib/anaconda/textw:文本安装模式的模块。和iw子目录含义是一致的,只是包含的是文本安装模式的前端字符用户界面类所在的模块,每个字符用户界面对应一个类,负责与用户的交互,字符界面的采用了python的snack库。
/usr/lib/anaconda-runtime: 有init和loader程序。这是两个静态编译的程序,不依赖其他库,就是编译anaconda源代码目录下的loader目录下的C代码得到。这两个程序会放在最后用来启动安装过程的Linux initrd image里面。
/usr/anaconda主目录:如果说用户界面类是处理安装程序外观的话,则anaconda主目录下的各python模块执行每个安装界面背后具体的安装行为,包括那些无用户界面安装步骤的安装操作。
由此可见,主执行体/usr/bin/anaconda调用的大量例程分布在/usr/lib/anaconda目录下,安装过程要用到的资源文件(例如背景图片)则分布在/usr/share/anaconda目录下。Python的许多内置模块则在目录/usr/lib/pythonXX下,其中XX指版本号。
上面分析的是已经编译好的anaconda目录结构,现在概览一下anaconda源代码包的结构。Anaconda主要用Python编写,图形界面前端用pyGtk库(参考http://www.pygtk.org/)和Glade界面描述文件(参考http://glade.gnome.org/)编写。用来启动环境、加载模块、加载anaconda主体的loader程序用C编写,一些其他的硬件相关的部分也是用C编写。另外,bash和python脚本还用在一些管理性的任务中。
需要知道,安装程序只是一个普通的用户程序,安装程序在能够运行之前,必须要启动操作系统才行,而这个时候,物理硬盘上尚且没有操作系统。
所以,一个安装光盘里,需要有引导程序(负责将操作系统内核和initrd.img加载到内存),操作系统内核和initrd(负责程序运行环境的构建)。另外,如果是一个安装光盘,那么需要有安装程序;如果是livecd,需要有live磁盘镜像。也就是说,需要有已经安装的操作系统磁盘镜像,这就是img文件。从理论上说,操作系统的安装过程和启动过程在前几步是完全相同的。
系统安装过程如下:
启动操作系统内核——加载initrd.img——运行初始化程序——根据初始化initrd中init程序的内容,决定是启动livecd还是ananconda来运行安装程序;如果是livecd,那么里面如果有installer程序,可以手动开启installer程序来安装操作系统,注意,此时调用ananconda等程序来安装操作系统,是用户行为,不是系统子自发的行为,已经没有操作系统的引导过程了(因为操作系统已经起来了)。
POST加电自检-->BIOS(Boot Sequence)-->加载对应引导上的MBR(bootloader)-->主引导设置加载其BootLoader-->Kernel初始化-->initrd—>/etc/init进程加载/etc/inittab。
由于传统的安装过程是ananconda控制的,而ananconda又会执行kickstart的配置文件,所以,我们有必要来了解一下kickstart的配置文件语法和大体框架:
line1~line6:基本配置:
Line 1 lang en_US.UTF-8 2 keyboard us 3 timezone US/Eastern 4 auth --useshadow --enablemd5 5 selinux --enforcing 6 firewall --disabled
Line 8 repo --name=a-base --baseurl=http://mirror.centos.org/centos/5/os/$basearch 9 repo --name=a-updates --baseurl=http://mirror.centos.org/centos/5/updates/$basearch 10 #repo --name=a-extras --baseurl=http://mirror.centos.org/centos/5/extras/$basearch 11 repo --name=a-live --baseurl=http://www.nanotechnologies.qc.ca/propos/linux/centos-live/$basearch/live
%packages syslinux kernel @admin-tools #packages removed from @admin-tools -sabayon -system-config-kdump #@admin-tools <end of package list> @base #package added to @base squashfs-tools #packages removed from @base -amtu -bind-utils
【安装后需要执行的shell脚本】
241 %post 242 243 #!/bin/bash 244 # 245 246 # FIXME: it'd be better to get this installed from a package 247 cat > /etc/rc.d/init.d/centos-live << EOF_initscript 248 #!/bin/bash 249 # 250 # live: Init script for live image 251 # 252 # chkconfig: 345 00 99 253 # description: Init script for live image. 254 255 . /etc/init.d/functions
kernel初始化所要工作的内容做下简单总结:
探测硬件->加载驱动(在initrd之中)->挂载根文件系统(initrd镜像中的init脚本完成)->rootfs(/sbin/init)
vmlinux是很小的,仅仅包含一些最基本的东西,不包含驱动程序,大概只有4M
驱动程序在initrd之中,我们也可以把驱动坐在vmlinuz中,但是由于存放vmlinuz的设备多种多样,所以需要编入内核的驱动也有很多,会造成内核臃肿,所以产生了initrd文件,引导程序初始化ramdisk,解决驱动多样问题。
4.2initrd与initramfs有什么去别?
ramfs是一种非常简单的文件系统,它直接利用linux内核已有的高速缓存机制(所以其实现代码很小,也由于这个原因,ramfs特性不能通过内核配置参数屏蔽,它是内核的天然属性),使用系统的物理内存,做成一个大小可以动态变化的的基于内存的文件系统。大小大概是16M
在早期的linux系统中,一般只有硬盘或者软盘被用来作为linux根文件系统的存储设备,因此也就很容易把这些设备的驱动程序集成到内核中。但是现在的嵌入式系统中可能将根文件系统保存到各种存储设备上,包括scsi、sata,u-disk等等。因此把这些设备的驱动代码全部编译到内核中显然就不是很方便。大小大概是4M
4.3安装程序中,images目录下的各种磁盘镜像文件是如何挂载的?
尚未解决