红联Linux门户
Linux帮助

构造Linux系统的图形化安装程序(三)

发布时间:2006-10-12 10:47:40来源:红联作者:fengmayi1
  分区功能和RAID、LVM支持

  本文是构造Linux的图形化安装程序系列文章的第三部分,作者将从基本的分区表结构开始,介绍分区功能的实现和如何支持RAID、LVM这些高级功能。

  分区功能对于Linux图形化安装程序来说,是一个非常重要的功能。它的基本功能是自动识别硬盘,并在硬盘上创建ext2类型的分区和交换分区。用户将此分区作为根分区,在其上进行Linux系统的安装。

  对于一个功能较全的安装程序,它还应该具备创建其他类型的分区的能力,包括reiserfs、fat等等,创建软件RAID分区,创建逻辑卷管理分区的能力。以及具有过滤合法安装点,根据选择的分区类型决定最合适挂接点的能力。分区能够动态的删除和修改,分区操作能够恢复到分区操作之前具体内容的状态。

  这个部分介绍的主要内容包括代码都是基于HappyLinux的安装程序,所有功能全部在HappyLinux3.0的安装程序中实现。您可以在安装盘的/HappyLinux/happyinst/usr/bin/perl-install目录下获得安装程序源码。

  1 安装程序分区模块介绍

  在图形化安装程序中,硬盘分区的一般流程是:

[align=center][/align]   

  装程序中与分区功能密切相关的模块包括:

  diskdrake.pm图形化的分区处理模块,它是分区功能的主控模块,处理与用户的交互,进行分区操作的合法性检查。
  diskdrake.rc分区操作窗口的资源文件,主要描述不同分区类型的表述。
  fs.pm完成挂接和格式化分区的操作,同时也生成/etc/fstab文件。
  fsedit.pm获得硬盘分区结构,完成添加、删除、修改分区的操作。
  lvm.pm提供创建、修改和获取逻辑卷管理分区的模块。
  partition_table.pm对分区表操作的逻辑副本进行操作的模块,包括分区操作的合法性判断、设置分区对齐、读取主分区和扩展分区、类型判断的函数。
  partition_table_dos.pm对dos类型的分区表进行操作的模块。
  partition_table_raw.pm直接存取硬盘分区表读取/写入分区信息。
  raid.pm对软件raid设备进行处理的模块。
文章评论

共有 3 条评论

  1. fengmayi1 于 2006-10-12 10:50:34发表:

      4 支持LVM类型的分区

      一般而言,磁盘分区的大小是固定的,它要求用户在安装系统时对分区空间的使用有大概的了解。在用户用尽了分区上所有的空间时,则要求重新分区或者移走一部分文件。

      LVM(Logical Volume Management)是逻辑卷管理的缩写。它的出现将物理磁盘分割成一些逻辑单位,来自于不同磁盘的分区能组成一个逻辑卷。此外,在需要时分区能被动态的加入和删除。举例来说,如果你有一个8GB的磁盘,其上有一个2GB的分区/usr,它的空间已经耗尽了。如果您要扩大/usr分区的话,必须首先创建一个更大的分区,然后将/usr的所有内容都拷贝到此分区中,改变/etc/fstab文件,重新启动。但是如果在系统中使用了LVM的话,你只需使用LVM中的命令,就可以简单的增大/usr。

  2. fengmayi1 于 2006-10-12 10:50:09发表:

      3 创建文件系统

      在分区操作结束之后,为了在其上进行安装,还需要在分区上创建文件系统。安装程序是使用系统命令,比如mkdosfs,mke2fs,mkreiserfs来创建文件系统。

    [code]sub format_ext2($@) {
      my ($dev, @options) = @_;
      
      $dev =~ m,(rd|ida|cciss)/, and push @options,
    qw(-b 4096 -R stride=16);
      push @options, qw(-b 1024 -O none) if arch() =~ /alpha/;
      #- 调用mke2fs创建ext2文件系统
      run_program::run("mke2fs", @options, devices::make($dev))
    or die _("%s formatting of %s failed", "ext2", $dev);
      }
      
      sub format_dos($@) {
      my ($dev, @options) = @_;
        #- 调用mkdosfs创建fat文件系统
      run_program::run("mkdosfs", @options, devices::make($dev))
    or die _("%s formatting of %s failed", "dos", $dev);
      }[/code]
      
      创建Reiserfs文件系统:

    [code]sub format_reiserfs($@) {
      my ($dev, @options) = @_;
      #- 调用mkreiserfs创建Reiserfs文件系统
      run_program::run("mkreiserfs", "-f", @options,
    devices::make($dev)) or die _("%s formatting of %s
    failed", "reiserfs", $dev);
      }[/code]
      
      在使用Reiserfs文件系统作为系统的根分区时,系统在启动的过程中需要加载模块reiserfs.o。RedHat 7.0以下的版本则不支持Reiserfs文件系统,所以很多基于RedHat的发行版本也不支持Reiserfs文件系统。如果您要在这样的系统上加入reiserfs支持,除了装载Reiserfs对应的rpm包之外,还要在生成初始启动镜像(initrd)时,在linuxrc中加载Reiserfs模块。

      这需要在/sbin/mkinitrd文件中加入下列语句:

      # 对于/etc/fstab中挂接的文件系统,如果它的类型不是ext2,那么必须加载设备模块。
      
    [code]  fs=$(awk '$2 == "/" {print $3 }' /etc/fstab)
      
      [ -n "$fs" -a "$fs" != "ext2" ] && findmodule $fs[/code]

  3. fengmayi1 于 2006-10-12 10:49:07发表:

      2 基本分区功能

      硬盘主分区由240字节的硬盘主引导记录(0000H-00EFH),64字节的硬盘分区表(01BEH-01FDH)以及最后两个字节的自举记录有效标志等三部分组成。主引导记录块的布局:

      硬盘0柱面0磁头1扇区;

      主引导记录代码区;

      第一个分区表 ;

      第二个分区表 ;

      第三个分区表 ;

      第四个分区表 ;

      主引导记录有效标志55H,AAH 。

      硬盘分区各个字段的意义是:

      字节位移 长度(字节) 字段含义。

      0 1 活动分区指示符。该值为80H,表示可自举分区(仅有一个);改值为00H,表示不可自举分区。该字节也称为自举标志。

      1 1 起始磁头号。

      2 1 起始扇区号(低6位)和起始柱面号的高2位。

      3 1 起始柱面号的低8位。

      4 1 分区上的系统标志。

      该值为01H,表示采用12位FAT格式的DOS分区。

      该值为04H,表示采用16位FAT格式的DOS分区。

      该值为07H,表示采用NTFS分区。

      该值为0BH,表示采用WIN98的FAT32格式的分区。

      该值为0CH,表示采用WIN98的FAT32格式的分区,支持LBA方式。

      该值为0FH,表示采用WIN95的扩展分区,支持LBA方式。

      该值为82H,表示采用LINUX SWAP格式的分区。

      该值为83H,表示采用LINUX EXT2格式的分区。

      该值为8EH,表示采用LVM格式的分区。

      该值为FDH,表示采用软件RAID格式的分区。

      5 1 结束磁头号。

      6 1 结束扇区号(低6位)和结束柱面号的高2位。

      7 1 结束柱面号的低8位。

      8 4 相对扇区号。

      12 4 该分区所用的扇区号。

      硬盘分区是以链接表的形式存在的,在每个硬盘上都存在一个主分区描述块,它可以描述四个分区,每个硬盘最多只存在四个主分区,其他的分区则为扩展分区。每个扩展分区是通过链接字段联结在一起。

      主分区使用的设备别名是从/dev/hda1到/dev/hda4,其后从/dev/hda5开始的分区,都代表扩展分区。

      读入分区表 #- 以下代码读入整个硬盘分区表形成分区的描述结构。

    [code] sub read($;$) {
      my ($hd, $clearall) = @_;
      if ($clearall) {
      partition_table_raw::zero_MBR_and_dirty($hd);
        return 1;
      }
      #- 读入主分区表,检测这分区表上扩展分区数,如大于1,则出错。
      my $pt = read_one($hd, 0) or return 0;
      #- 主分区描述数组存入primary变量中。
      $hd->{primary} = $pt;
      undef $hd->{extended};
      #- 校验主分区,校验包括:分区是否重叠,是否存在未知空洞。
      verifyPrimary($pt);
      #- 如果存在扩展分区,则读入扩展分区,这时要检测扩展分区是否重叠,是否存在循环联结。
      eval {
        $pt->{extended} and read_extended($hd, $pt->{extended}) || return 0;
      };
      #- 对读出的分区指定其设备号,主分区/dev/hda1(/dev/sda1)到/dev/hda4(/dev/sda4)。
      assign_device_numbers($hd);
      #- 除去扩展分区中的空连接。
      remove_empty_extended($hd);
      1;
      }[/code]

      将分区操作写入分区表 #- 此操作只是根据用户的操作写分区表,包括写入分区大小分区类型等信息。

    [code] sub write($) {
      my ($hd) = @_;
      $hd->{isDirty} or return;
      #- 设置引导标志
      for ($hd->{primary}{raw}) {
      (grep { $_->{local_start} = $_->{start};
    $_->{active} ||= 0 } @$_) or $_->[0]{active} = 0x80;
      }
      #- 校验分区,校验包括:分区是否重叠,是否存在未知空洞。
      verifyParts($hd);
      #- 写入分区表
      $hd->write(0, $hd->{primary}{raw}, $hd->
    {primary}{info}) or die "writing of partition table failed";
      
      $hd->{isDirty} = 0;
      $hd->{hasBeenDirty} = 1;
      if ($hd->{needKernelReread}) {
      sync();
        $hd->kernel_read;
        $hd->{needKernelReread} = 0;
      }
      }[/code]