转自http://zhu8337797.blog.163.com/blog/static/170617549201082410351788/

anaconda  

2010-09-24 22:05:11|  分类: linux实践 |  标签:安装  anaconda  py  dispatcher  self   |字号 订阅

安装程序anaconda分析第一步,stage2.img解压

很stupid的题目吧,可偏偏就是这一步,耗掉了我8个小时,还一事无成。最后在某某同学帮助下(名字没记住,对不住啦,再见到的话一定问明姓名补上),又耗掉近一个小时才搞定。

原本计划按照王柏生那篇《redhat 安装程序 anaconda分析》来进行安装程序分析,后来发现redhat和Asianux似乎还是有很多细节上的不同的,没法照搬。恩,边看边改吧~

首先第一步,解开stage2.img,这是当安装介质是cdrom时的安装映像文件。注意,ISO虚拟的光驱被挂载在/media/Asianux,这里stage2.img实际上是在/media/Asianux/images/stage2.img

当采用 mount来解析这个映像文件的时候,大陷阱来了~

02 - linux-ul - unix-EA

 

由于stage2.img是来自发行版的live-cd ,采用的是squashfs文件系统。我却傻傻的用iso9660,ext2,ext3一通瞎试,而且网上关于这个错误的解决方案也是千奇百怪,不靠谱。白浪费了8小时。其实用file命令查看一下,就会发现问题了,愚蠢啊~

file stage2.img
stage2.img: Squashfs filesystem, little endian, version 3.0, 68102631 bytes, 4938 inodes, blocksize: 65536 bytes, created: Wed Aug 29 16:58:29 2007

squashfs 是在linux下将目录或文件打包成只读文件系统。如果你想实现压缩的话,需要kernel
的支持,请访问如下链接:http://www.squashfs-lzma.org/

SquashFS 是一种可用于 flash 设备的压缩式 Linux 只读文件系统(Linux 支持多种只读文件系统,最有用的两种是 cramfsSquashFS。)。可以在很多 Live CD Linux 发行版中找到 SquashFS。除了支持 zlib 压缩外,SquashFS 还使用 Lembel-Ziv-Markov chain Algorithm (LZMA) 改善压缩并提高速度。您可以通过 mksquashfs 和 loopback 设备在标准 Linux 系统上使用 SquashFS。有时它也可以用于 UnionFS,实现了文件系统的联合挂载(文件系统互相叠加)。SquashFS 使用 LZMA一组补丁,因此提供了较好的压缩功能和性能。

SquashFS这个东西最大的作用就是其只读,不管你是什么用户,所有的文件和目录都是只读的。 如果你想实现自己的东西不被修改,那么就用这个文件系统吧。 如果想将自己的发行版做成live-cd的话,请将你的内核打上支持LZMA的patch.

解析该映像文件命令:

mount -o loop -t squashfs /media/Asianux/images/stage2.img /mnt

加载成功后,可以通过df -h命令查看。

加载后/mnt中共包含如下目录:

  etc  lib  modules  proc  usr  var
这就是我们的安装程序的运行根目录!包括安装程序anaconda.busybox等程序。

[题外话]

1、losetup 对loop设备进行操作:

losetup /dev/loop0 /media/Asianux/images/stage2.img
losetup -a

2、查看fstab

cat /etc/fstab

3、看系统出错信息

dmesg | tail

++++++++++++++++++++++++++++++++++

引言

Linux 的安装过程可以分为两个阶段,第一个阶段就是加载内核,创建供后续安装过程使用的系统环境,第二阶段就是加载系统安装程序,执行具体的安装过程。对于第一阶段,有不少资料作了比较详细的介绍,而对于第二阶段,也就是具体的安装过程,却鲜有资料介绍,本文作者结合自己在实践中的心得体会,针对redhat9.0的安装程序anaconda作了粗略的分析。

为了抓住主线,文中所列代码片断基本都经过格式调整,并裁减掉了不影响理解的细节,读者可参照源代码。另外,anaconda是用python语言写的,所以读者最好具备一些python语言的基础和面向对象的基本知识,如果有过图形界面程序的设计的经验,则无论是对图形安装模式还是字符安装模式安装过程(本文只讨论图形安装模式)的理解都会有很大帮助。


回页首

1 概述

系统启动,加载启动映像,在内存中建立了linux系统环境后,解析安装程序映像文件,将安装程序载入内存,执行主执行程序anaconda,该程序是具体安装程序的一个口,负责启动具体的安转过程,完成linux系统的安装。

我们首先看一下安装映像文件。进入redhat9.0第一张系统盘的redhat/base目录,其中stage2.img就是当安装介质为CD-ROM时的安装映像文件。我们采用如下命令解析该映像文件(注意:命令中的挂载点/mnt/stage2要根据读者的实际情况修改):

mount -o loop /mnt/cdrom/Redhat/base/stage2.img /mnt/stage2

解析后,我们可以看到,安装程序的主执行体anaconda在/mnt/stag2/usr/bin目录下,其它安装脚本模块均在/mnt/stage2/usr/lib/anaconda目录下,今后的行文中,除非是anaconda主执行体,其余均指/mnt/stage2/usr/lib/anaconda目录下的模块,并将该目录简称为anaconda主目录。

我们先看一下anaconda主目录的结构:

  • installclasses子目录中的各个模块定义了在安装过程中用户可选择的安装类型。redhat9.0下包含了四个文件workstation.py,server.py,custom.py和personal_desktop.py。其中,workstation.py描述了工作站安装类型,server.py描述了服务器安装类型,custom.py描述了用户自定义安装类型,personal_desktop.py描述了个人桌面安装类型。每个安装类型描述文件根据相应安装类型的特点,分别对安装步骤、分区策略以及安装包的取舍给出了不同的方案。
  • Iw子目录下包含所有安装图形界面类所在的模块,每个图形界面对应一个类,负责相应安装步骤图形界面的具体外观显示及与用户的交互,(可能)调用anaconda主目录下的相关安装行为模块完成具体的安装操作。
  • textw子目录和iw子目录含义是一致的,只是包含的是字符安装模式的前端字符用户界面类所在的模块,每个字符用户界面对应一个类,负责与用户的交互,字符界面的采用了python的snack库。
  • 如果说用户界面类是处理安装程序外观的话,则anaconda主目录下的各python模块则执行每个安装界面背后具体的安装行为,包括那些无用户界面安装步骤的安装操作。

Python的许多内置模块在目录/mnt/stage2/usr/lib/pythonXX下,其中XX指版本号。另外可参考redhat的anaconda源码包,所有的相关工具都在源码包里,读者在理解了安装过程的原理后,可修改源码,重新编译,然后搭建测试环境进行测试。


回页首

2 总体分析

图形安装界面采用python + Gtk开发,各个模块(类)之间的逻辑关系可用下图表示:


图1 图形安装模式下模块(类)逻辑关系图

XML error: The image is not displayed because the width is greater than the maximum of 580 pixels. Please decrease the image width.

安装程序逻辑上可划分为三个层次,我们先看最主要的一层:调度中心。可以说,Dispatcher类和InstallControlWindow类控制了整个安装程序的运转,理解这两个核心类的功能及其与用户界面类和安装行为类的逻辑关系,就基本上理解了整个安装程序。

Dispatcher类在anaconda主目录下的dispatch.py模块中,负责整个安装流程的控制,在安装过程中,某些安装步骤有的需要前置安装操作,有的又需要后置安装操作,而某些安装操作则是没有用户界面的,我们统称这些安装操作为无用户界面的安装操作,那么,这些没有用户界面的安装操作由谁来调度运行呢?答案就是Dispatcher。

InstallControlWindow 类在 anaconda 主目录下的 gui.py 模块中,控制安装过程中前端图形界面的显示,总体调度各个安装图形界面类,InstallControlWindow 建立图形界面的主窗体,每个具体的图形安装界面可视为其子窗体。InstallControlWindow 调用 Dispatcher 控制整个安装流程。

安装过程中,每个具体的图形安装界面均对应一个具体的类,由其对应的具体的类完成具体的安装任务,我们将这些图形界面类归为前端显示层,位于iw目录下的模块中。

anaconda将某些用户界面类中的具体安装操作分离出来,放到了另外一些模块中,这些模块放在了anaconda的主目录下。由Dispatcher直接调用的没有用户界面的安装步骤对应的函数也放在了anaconda的主目录下,我们将这些模块归为安装行为层。

图中虚线表达的含义是"可能调用"。如在安装过程中,负责前端显示的package_gui.py模块可能要调用负责安装行为的packages.py模块或其它负责安装行为模块中的类或函数。

2.1 主要控制类分析

2.1.1 Dispatcher

该类在anaconda主目录下的dispatch.py模块中。无论是图形模式安装还是字符模式安装,都由该类来控制安装流程,所以,分析该类时,我们将图形用户界面和字符用户界面统称为用户界面,涉及到字符安装模式的叙述,读者暂时可略过,读到字符安装模式分析时,再回头来看。dispatch.py模块中有一个序列(sequence)数据结构:installSteps。installSteps中记录了有序排列的整个安装过程中所有可能的安装步骤,在生成具体的Dispatcher实例时,会根据安装类型制定对此进行相应裁减。

installSteps中的条目(item)有如下两种格式,第一种格式:( name, tuple)

这种格式表示有用户界面的安装步骤。其中,name代表安装步骤的名称,tuple(元组,python的一种内置数据类型)存放创建相应安装步骤的用户界面的参数。

第二种格式:( name, Function, tuple)

这种格式表示没有用户界面的安装步骤,其中,name代表安装步骤的名称,Function指安装操作的具体执行函数,tuple存放的是传递给Function的参数。该安装步骤直接由Dispatcher调度进行。

下面我们结合具体的程序具体地解释一下上面的叙述,加深我们对安装流程的理解。

首先看下面从序列installSteps中截取的一个程序片断:

installSteps = [  ……  ("partitionmethod", ("id.partitions", "id.instClass")),      ("partitionobjinit", partitionObjectsInitialize, ("id.diskset","id.partitions","dir", "intf")),      ("partitionmethodsetup", partitionMethodSetup, ("id.partitions","dispatch")),      ("autopartition", ("id.diskset", "id.partitions", "intf", "dispatch")),      ("autopartitionexecute", doAutoPartition, ("dir", "id.diskset","id.partitions", "intf",                                                 "id.instClass", "dispatch")),      ("fdisk", ("id.diskset", "id.partitions", "intf")),  ……  ]  

我们假设当前安装步骤为partitionmethod,根据其条目的数据格式可以看出该安装步骤具有用户界面,根据安装步骤名称,如果熟悉linux安装过程,读者应该可以猜出这个安装步骤是分区方式选择,对应该安装步骤的用户界面的类是PartitionMethodWindow,该类属于前端显示层,在iw目录下partitionmethod_gui.py模块中。我们看一下该类的部分代码:

class PartitionMethodWindow(InstallWindow):      def getNext(self):          if self.useAuto.get_active():              self.partitions.useAutopartitioning = 1          else:              self.partitions.useAutopartitioning = 0  ……  

我们可以想象当用户在用户界面上点击"下一步"按钮时getNext函数被调用,分析该函数,我们可以看出,当用户选择自动分区后,该函数设置partitions.useAutopartitioning = 1,如果选择手动分区,则设置partitions.useAutopartitioning = 0。

本步骤完成,安装过程进行下一步,Dispatcher首先在installSteps中取下一个条目"partitionobjinit",该条目中含有function,说明此安装步骤没有用户界面,Dispatcher直接调用函数(Function)partitionObjectsInitialize,从字面上我们就可以看出,该函数是对分区操作进行相关初始化方面的操作,执行完该安装步骤后,Dispatcher继续调用下一个安装操作"partitionmethodsetup",该安装步骤也没有用户界面,Dispatcher直接调用函数partitionMethodSetup,函数partitionMethodSetup和partitionObjectsInitialize都属于安装行为层,在anaconda主目录下的partitioning.py模块中。我们看一下函数partitionMethodSetup的部分代码:

def partitionMethodSetup(partitions, dispatch):      dispatch.skipStep("autopartition", skip = not partitions.useAutopartitioning)      dispatch.skipStep("autopartitionexecute", skip = not partitions.useAutopartitioning)  ……  

我们看出,如果用户选择手动分区,即partitions.useAutopartitioning = 0,则not partitions.useAutopartitioning) = 1,即skip = 1,那么安装流程控制实例Dispatcher就会略过(skipsteip)安装步骤"autopartition"和"autopartitionexecute"继续下一个安装步骤,下一个安装步骤有用户界面,对于图形安装模式,Dispatcher将控制权交给InstallControlWindow,对于字符安装模式,Dispatcher将控制权交给InstallInterface。

我们再分析另一个从installSteps中截取的片断:

installSteps = [  ……  ("bootloaderadvanced", ("dispatch", "id.bootloader", "id.fsset", "id.diskset")),      ("networkdevicecheck", networkDeviceCheck, ("id.network", "dispatch")),      ("network", ("id.network", "dir", "intf")),  ……  ]  

我们假设当前安装步骤为"bootloaderadvanced",其后的另一个具有用户界面的安装步骤为网络配置"network",而进行网络配置的前置条件就是安装的主机要具有网络设备,因此,系统安装程序在"network"之前插入了步骤"networkdevicecheck"。假设安装过程从当前安装步骤"bootloaderadvanced"进行到下一个安装步骤"networkdevicecheck",该安装步骤没有用户界面,Dispatcher直接调用函数networkDeviceCheck,我们看一下该函数的代码(network.py):

def networkDeviceCheck(network, dispatch):      devs = network.available()      if not devs:          dispatch.skipStep("network")  

可以看到,该函数首先检测是否存在网络设备,如果没有网络设备,Dispatcher则忽略安装步骤"network"。这里,可以说函数networkDeviceCheck是有用户界面的安装步骤"network"的前置操作。

通过上面的分析,我想我们不难理解为什么Dispatcher被称为"主要安装流程控制类"了。其它的安装步骤控制基本相同,我们不一一分析了。

下面我们看一下Dispatcher的主要接口。

gotoNext & gotoPrev:这两个接口分别从当前安装步骤前进(后退)到下一个(上一个)具有用户界面的安装步骤,在图形界面安装模式下,由installcontrolwindow调用,在字符模式下,由InstallInterface调用。这两个函数只是简单的设置安装方向,然后调用movestep函数,其核心操作是movestep。我们来重点分析movestep函数:

    def moveStep(self):  ……  if self.step == None:   self.step = self.firstStep  else:  self.step = self.step + self.dir   while ((self.step >= self.firstStep and self.step < len(installSteps))                 and (self.skipSteps.has_key(installSteps[self.step][0])                      or (type(installSteps[self.step][1]) == FunctionType))):  info = installSteps[self.step]       if ((type(info[1]) == FunctionType) and (not self.skipSteps.has_key(info[0]))):  (func, args) = info[1:]     rc = apply(func, self.bindArgs(args))       if rc == DISPATCH_BACK:         self.dir = -1     elif rc == DISPATCH_FORWARD:         self.dir = 1        self.step = self.step + self.dir  if self.step == len(installSteps):      return None      

我们重点看一下程序while循环体,首先看一下循环条件:当下一个安装步骤是合法的,即在第一个安装步骤和最后一个安装步骤之间,并且(and)该步骤被裁减了或者该步骤是一个无用户界面的安装步骤,即installSteps的条目的第二个元素是一个function,则进入循环体。进入循环后,Dispatcher直接调用该函数执行安装操作,其中bindArgs是Dispatcher类的一个函数,负责参数解析,这里的apply是python的的一个内置方法,用来执行函数,apply接口的第一个参数是要运行的函数名称,第二个参数是传给该函数的参数。如果下一个安装步骤依然无用户界面,则继续循环,直到下一个没有被裁减的具有用户界面的安装步骤,对于图形安装模式,Dispatcher将控制权交给InstallControlWindow,对于字符安装模式,Dispatcher将控制权交给InstallInterface。如果安装过程完成则退出循环。

currentStep:Dispatcher类的另一个主要接口,取得当前的安装步骤及其相关信息返回给调用者。在图形安装模式下,该函数主要由InstallControlWindow调度图形用户界面类时调用,在字符模式下,主要由InstallInterface调度字符用户界面时调用,这两个类通过该接口取得当前安装步骤的用户界面对应的类及创建该用户界面类的实例所需的信息。

另外,Dispatcher类的主要接口还有skipStep(self, stepToSkip, skip = 1, permanent = 0)是裁减安装步骤函数。setStepList(self, *steps)是安装步骤设置函数,主要由安装类型实例调用,每个安装类型会根据自身的特点设置安装步骤。这些接口的实现逻辑都比较简单,这里不一一给出分析了。

至此,Dispatcher的主体基本分析完了,看完下面InstallControlWindow以及后面字符安装模式的InstallInterface类的分析,我们对Dispatcher将会有更好的理解。


回页首

3 InstallControlWindow

该类在anaconda主目录下的gui.py模块中。首先我们先看一下启动图形安装界面的入口函数run:

    def run (self, runres, configFileData):  self.configFileData = configFileData      self.setup_window(runres)      gtk.main()      

该函数调用了setup_window接口,该接口调用gtk"绘制"图形安装界面的主窗体,然hou控制权交给了gtk。

nextClicked & prevClicked:这两个接口分别执行从当前图形安装界面向前(向后)到下一个图形安装界面的操作,我们可以想象安装过程中当用户点击"下一步"或"上一步"按钮时,这两个函数被调用。这两个函数首先调用主流程控制Dispatcher实例向前(向后)前进到下一个图形安装界面,然后调用setScreen函数,从函数名称的字面上看,setScreen是设置图形界面的,那么接下来我们看一看该函数的具体功能,在分析其之前,我们要首先看一下gui.py模块中的一个字典数据结构:stepToClass。该字典中记录了安装过程中所有的具有图形用户界面的安装步骤。

stepToClass = {      "language" : ("language_gui", "LanguageWindow"),  "keyboard" : ("keyboard_gui", "KeyboardWindow"),  ……  }  

每一个条目从左到右依次是安装步骤名称、图形界面对应的类所在的模块,图形界面类的名称。如language为安装步骤名称,language_gui为该步骤对应的图形界面类所在的模块language_gui.py,LanguageWindow为图形界面对应的类名。理解了该数据结构后,我们开始分析setScreen函数:

def setScreen (self):   (step, args) = self.dispatch.currentStep()   if not stepToClass[step]:       if self.dir == 1:     return self.nextClicked()       else:     return self.prevClicked()   (file, className) = stepToClass[step]  newScreenClass = None   s = "from %s import %s; newScreenClass = %s" % (file, className, className)      while 1:       exec s          break   self.destroyCurrentWindow()      self.currentWindow = newScreenClass(ics)   new_screen = apply(self.currentWindow.getScreen, args)      self.installFrame.add(new_screen)      self.installFrame.show_all()  ……  

前面的nextClicked和prevClicked函数已经通过Dispatcher将要进行的安装步骤标记为当前安装步骤,所以该函数首先通过Dispatcher的currentStep从Dispatcher的数据结构installSteps中取得当前安装步骤名称及相关信息,接下来,做了一下判断,如果Dispatcher的当前安装步骤不在字典stepToClass中,则忽略该步骤,调用nextClicked或prevClicked继续下一个图形界面安装步骤,直到下一个步骤在字典stepToClass中。验证通过后,从字典stepToClass中取得当前图形安装界面对应的类及该类所在模块,然后导入该模块并创建图形安装界面的实例,销毁前一个图形安装界面,并将新创建的图形界面实例置为当前安装界面,调用图形安装界面实例的getScreen函数生成该安装步骤的图形用户界面,然后显示。

至此,InstallControlWindow的主要逻辑已经分析完了,接下来涉及每个具体安装界面及其安装操作读者可以到iw目录下逐个深入分析。


回页首

4 主执行程序anaconda分析

前面我们比较详细的分析了图形模式和字符模式的安装过程,对于图形安装过程,图形环境运行是建立在X Server基础上的,因此在进行图形安装时,必须运行X。因此,简单的说,对于图形模式,anaconda的主执行体就作了两件事:1、运行X服务器(如果X没有运行)。2、启动图形模式安装过程。而对于字符模式,anaconda的主执行体就作了一件事,启动字符模式安装过程。

4.1 启动X server

如果是图形模式安装,则anaconda首先要启动X server。anaconda首先检测图形正常显示所需的硬件资源。Python提供了许多内置模块实现相关硬件的操作。这些模块在目录pythonXX/rhpl下(XX表示版本号,在笔者的机器上路径是/mnt/stage2/usr/lib/python2.2):

Videocard.py、Monitor.py、Mouse.py、keyboard.py分别是显示卡、监视器、鼠标和键盘的相关操作和配置数据。xserver.py - 图形模式下X server启动初始化方面的工作,包括相关硬件的探测和X server的启动,xserver为videcard、monitor和mouse的探测提供了统一个接口,实际调用的是相应硬件模块的接口。

下边的程序片段探测显示卡、监视器和鼠标、键盘,并且利用xhwstate记录该配置状态,供后续安装过程使用。

import rhpl.xserver as xserver   (videohw, monitorhw, mousehw) = xserver.probeHW(skipDDCProbe=skipddcprobe,        skipMouseProbe = skipmouseprobe)  kbd = keyboard.Keyboard()  if keymap:      kbd.set(keymap)  xcfg = xhwstate.XF86HardwareState(defcard=videohw, defmon=monitorhw)  

硬件检测完成后,启动X server的条件已就绪,如果X server没有启动,并且安装模式为图形模式,则启动X server:

          xsetup_failed = xserver.startXServer(videohw, monitorhw, mousehw, kbd,        runres,        xStartedCB=doStartupX11Actions,        xQuitCB=doShutdownX11Actions,        logfile=xlogfile)        

该调用除了传递相关硬件的配置信息外,还传递了两个函数。

doStartupX11Actions函数在X server启动时调用,该函数主要是启动窗口管理器,设置相关资源。

doShutdownX11Actions函数在X server退出时调用,关闭窗口管理器。

4.2 启动安装过程

我们前面分析安装过程原理时指出:安装的流程由Dispatcher控制,对于图形模式,图形模式的前端显示及与用户的交互由InstallControlWindow调度,而字符模式的前端显示层由InstallInterface调度。因此,启动安装过程,实际就是创建主要控制类的实例,调用实例的接口,启动安装过程,然后再由这几个主要的控制类的实例创建具体安装界面,创建安装行为类的实例,调用具体的函数完成具体的安装过程。

  • 创建实例

    1. 创建dispatch实例
    dispatch = dispatch.Dispatcher(intf, id, methodobj, rootPath)

    2. 创建InstallInterface实例

    对于字符模式,前端字符用户界面由InstallInterface调度。而对于图形模式,我们在前面分析时,没有提到InstallInterface类,其实在图形模式下,也有这么一个同名类,在模块gui.py中,但在图形安装模式下,这个类的作用很小,除了封装了创建常用对话框(包括messageWindow,progressWindow,exceptionWindow等)的接口外,一个主要的作用就是为创建installcontrolwindow实例提供了一个接口,为什么不在anaconda主执行程序中直接创建installcontrolwindow实例呢?个人认为可能是为了保证代码的一致性。

        if (display_mode == 'g'):          from gui import InstallInterface  if (display_mode == 't'):      from text import InstallInterface  if display_mode == "t":      intf = InstallInterface ()  else:      intf = InstallInterface ()      

    3. 创建installcontrolwindow实例

    installcontrolwindow实例在gui.py模块中的InstallInterface类的接口run中创建,该接口创建了InstallControlWindow实例后运行InstallControlWindow实例的run接口启动图形安装界面:

                def run(self, id, dispatch, configFileData):    ……          self.icw = InstallControlWindow (self, self.dispatch, lang)          self.icw.run (self.runres, configFileData)          

  • 启动安装过程

    安装控制类的实例创建完成后,调用其相应接口启动安装过程。对于字符安装模式,则直接调用InstallInterface实例的run接口。而对于图形安装模式,则是由InstallInterface实例的run接口间接的调用installcontrolwindow实例的run接口。

    intf.run(id, dispatch, configFileData)  

    另外,在启动安装过程前,anacoanda的主执行程序作了大量的繁琐的准备工作,主要包括引用模块路径设置、参数解析、内存检测、安装类型设置、创建安装介质实例等等。

anaconda安装程序较大,限于篇幅,文中分析不可能面面俱到,读者可以在理解程序运行的主要逻辑的基础上,参照原代码进一步分析。限于作者水平,分析中难免存在偏颇,恳请读者多多指正,欢迎来信讨论。

 

GNU/Linux开源,这个意义实在是非常的广泛,目前在distrowatch上表现活跃的300个发行版代表了GNU/Linux的主流,然而细心的Linux爱好者会发现CentOS-based distribution designed based on Slackware Linuxa distribution built from source software packages for Red Hat Enterprise Linuxa user-friendly Ubuntu-based distributionan Debian-based distribution等关键词汇,目前大多数的发行版基本上都是源于RedhatDebian/UbuntuSuseSlackware等版本的衍生态,而构建Based Distribution的目的有很多,不乏有技术交流、功能完善、以及管理、更新Bug软件包等需求,同样这些Based Distribution也为Linux爱好者构建自己的Linux发行版本提供了很好的参照。本文作为独辟蹊径的系列文章,将带领大家初探基于Cenotos 5.2Linux发行版构建方式,为进一步深入研究提供一个基础。
  要实现基于CentosLinux发行版本的构建,首先需要了解一下Linux启动过程以及Linux启动文件相关的了解,同时要对Linux发行版本的光盘结构以及软件包的结构进行了解分析。从主机加电到系统服务加载运行,Linux的启动(Linux安装的过程雷同)大致需要经历如下的过程:

第一阶段:
加载bios的硬件信息,并获取第一个启动的设备的代号;读取第一个启动设备的mbr的引导加载程序(lilogrub)的启动信息;加载核心操作系统的核心信息,核心开始解压缩,并且尝试驱动所有硬件设备;
分析此阶段是很有价值的,即便是 Linux 系统的安装也需要加载内核并解压内核、加载各类外设的驱动信息,构建一个最小化的 Linux 的文件系统以执行第二阶段的进程。
第二阶段:
核心执行init程序并获取运行信息;init执行/etc/rc.d/rc.sysinit文件;启动核心的外挂模块(/etc/modprobe.conf)init执行运行的各个批处理文件(Scripts);init执行/etc/rc.d/rc.local文件;执行/bin/login程序,等待用户登陆;登陆之后开始以shell控制主机。
  通俗的一个说法, Linux 的光盘安装就是在第一阶段由 stage2.img 构建产生的最小化的 Linux 文件系统之上运行 anaconda 之类的安装程序,完成 Linux 系统的安装过程。在 Linux 安装过程中第二阶段就是运行 anaconda 并配合系统安装预设选项完成对系统安装。
  构建 Base Centos Distribution Linux 发行版可以简单分为两种方式,第一种是通过结合 Kickstart 安装预配置文件对 Centos 系统安装的软件包并结合 Kickstart post pre 的脚本对安装的系统进行初始化的配置;第二种方式是通过添加修改 stage2.img 所生成的 Linux 文件系统达到定制内核、在安装过程添加定义的向导信息等。第一种方式实现便捷、 Kickstart X 界面工具操作也相对简单,如要略去光盘中不安装不需要的软件包,并添加第三方的 rpm 或者 tar.gz 源码包,就需要深入研究 repodata 中的 comps.xml 的基于 yum 的软件包依赖关系的定义,并能够有基本的 shell 脚本的累加能力,将要安装的软件包及设置通过脚本实现。相对第二种方式的不足之处就是还是使用 Centos 的系统并没有对内核或其他参数做明确的发布调整,故此第二种方式就深入修改 stage2.img anaconda 相关的配置实现,以达到发布独立有别于 Base Centos Distribution Linux 版本。
  基于 Cenotos Linux 发行版的目的是为了在系统中能够快速,正确地建立 Linux 系统环境。实现的方式以分析 Centos 的安装光盘为起点,在掌握对应的技巧方法,同时建立相应的测试环境。
   centos 5.2 DVD 介质为例,光盘中包含的主要与定制相关的目录如下:

isolinux目录存放光盘启动时的安装界面信息

repodata目录是与RPM包安装相关的依赖信息

images目录包括了必要启动映像文件

CentOS目录存放安装软件包信息

.discinfo文件是安装介质的识别信息,此文件不可缺少。

  下面将重点剖析一下 images isolinux 的目录中的文件及其作用,相对 Centos repodata 的目录在深度定制时的意义要大得多。
images 文件夹包含了引导启动的映像文件,主要的为 boot.iso 文件其中包含信息如下:
|----vmlinuz Linux内核
|----ldlinux.sys 引导Linux的系统文件
|----syslinux.cfg Linux内核引导参数配置文件
|----initrd.img 内存虚拟文件系统映像文件
|----*.msg文件 引导时的各种提示信息文件
其中,initrd.imgLinux ext2文件系统,构成如下:

initrd.img
|----/bin
|----/dev
|----/etc
|----/module
|----/sbin ------ loader
安装程序装载器
|----/tmp
|----/var
可执行文件/sbin/loader的任务是判断安装介质的有效性,并从中执行安装程序。
  在系统启动时被执行后在内存建立起了 Linux 内核 , 并根据配置文件 syslinux.cfg 装载虚拟文件系统,形成了完整的 Linux 系统,为后续的工作提供了必要的操作系统环境。可以通过如下命令查看 boot.iso 中的文件:
#mount -o loop boot.iso /mnt
#cd /mnt
## tree
.
|-- TRANS.TBL
`-- isolinux
|-- TRANS.TBL
|-- boot.cat
|-- boot.msg
|-- general.msg
|-- initrd.img
|-- isolinux.bin
|-- isolinux.cfg
|-- memtest
|-- options.msg
|-- param.msg
|-- rescue.msg
|-- splash.lss
`-- vmlinuz
images 文件夹的 stage2.img 是当安装介质为 CD-ROM 时的安装程序映像文件。
这里主要讨论stage2.img的内容
stage2.img        
  |----/etc
        |----/modules
        |----/proc
        |----/usr----/bin----anaconda        
安装程序主执行文件
        |
        |------/lib-----/anaconda               
安装程序脚本文件目录
     |          |----/installclasses        
        |          |----/iw
        |          |----/texttw               
         |          |----*.py
        |
        |------/share---/anaconda               
安装程序资源文件目录
         |         |----/help
        |                   |----/pixmaps

安装引导图形资源目录,包括安装过程中使用到的所有位图,图标,可以通过GMIP等工具修改
   stage2.img 映像文件中的主要部分是安装程序 anaconda ,它的主执行体是 /usr/bin 下的 anaconda ,由其调用的大量例程分布在 /usr/lib/anaconda 下,而安装过程中要用到的资源文件分布在 /usr/share/anaconda 下。可以通过执行如下命令具体查看 stage2.img 中的内容:
#mount -o loop -t squashfs stage2.img /mnt
#cd /mnt
#ls
etc lib modules proc usr var
顺带说一下 anaconda 安装程序,主要用 Python 语言写成,它是一种解释性的,面向对象的脚本语言,在其源码目录中有很多 py 的文件就是。要全面完成基于 Centos Linux 发行版,使用和学习 shell Python 是很有必要的, :-D
anaconda
  |-------------------/bootdisk
启动盘目录
  |-------------------/docs
文档目录
  |-------------------/help
安装过程帮助系统目录
  |-------------------/installclasses
安装类型分类目录,常由四个文件workstation.py , server.py , laptop.pycustom.py来描述workstation(工作站)安装类型,server(服务器)安装类型,laptop(膝上型电脑)安装类型和custom(自定义)安装类型。
  |-------------------/iw
安装各步骤响应目录,子目录中各文件定义了在图形界面安装状态时各步骤对NextPrev的响应函数。
  |-------------------/loader
安装程序装载器目录
  |-------------------/pixmap
图形资源目录,包括安装过程中使用到的所有位图,图标。
  |-------------------/utils
安装程序实用工具目录
  |-------------------*.py
Python脚本文件 
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐