Chinaunix首页 | 论坛 | 博客
  • 博客访问: 18681
  • 博文数量: 11
  • 博客积分: 400
  • 博客等级: 下士
  • 技术积分: 115
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-07 13:06
文章存档

2011年(1)

2009年(10)

我的朋友
最近访客

分类: LINUX

2009-12-16 23:17:08

由于拿到别人的一台装有RHEL5系统机器,无意中发现了一个有趣的现象。

在这台机器中有四个分区,sda1(boot分区) sda2(系统所在的分区) sda3(也是一个装有系统的分区,双系统)swap

问题在这个地方:

/boot/grub/grub.conf里,根是这样定义的:

        kernel /vmlinuz-2.6.18-128.el5 ro root=/dev/sda2 vga=773

/etc/fstab里却有点变化:

/dev/sda3        /         ext3    defaults        1 1

这显然是一个错误的写法。按照我的理解,如果这样写的话,最终进到系统里,系统的根分区应该是/dev/sda3。可是实际上却不是这样,进入系统后,看到的情况是,用,dfmount查看,会看到分区与挂载点的关系是/dev/sda3 on / type ext3 (rw),但进入到根目录,正在使用的内容却是/dev/sda2上面的。

 

其实是一个很简单的问题,因为从系统的启动来看,根分区是最先也是一直被挂载的,而且在grub里面被定义了位置。但疑惑的是,在系统看来,为什么/dev/sda2变成了/dev/sda3,引起了对应关系的错乱,是哪个操作过程引起的bug呢?于是,我的爱折腾的心又起。

 

我首先测试了mount的特点,发现了几个以前常以为不应该的问题(RHEL5RHEL4没测,忘了):

1、  /etc/fstab里面,/的挂载信息不一定要放在第一行。

2、  一个挂载点可以被挂载多次,后挂载的会覆盖新挂载的内容。

3、  一个分区可以被挂载多次到不同的挂载点下。

4、  一个挂载点正在被使用也可以被其他的分区覆盖挂载,只是不能umount

 

虽然弄清了上述问题,但还是不能想不通我的疑惑,因为系统启动的时候,根分区是以只读挂载的,在加载完kernelinitrd以及系统初始化后,会以rw的方式重新挂载根文件系统。那么根据第二点,和第四点,就说不通了,而且为什么会出现设备号混乱的情况。

看来问题出在重新挂载的过程。

通过查看系统启动时的屏幕显示,可以知道系统启动的大致过程。

1、  BIOSàMBRàgrub

2、  kernel boot

3、  waiting for driver initialization

4、  Creating root device ; Mounting root filesystem(readonly).

5、  注意这一段:

EXT3fs:INFO:recovery required on readonly filesystem.

EXT3-fs:write access will be enabled during recovery.

kjournald starting. Commit interval 5 seconds.

EXT3-fs:recovery complete.

EXT3-fs:mounted filesystem with ordered data mode.

Setting up other filesystem.

Setting up new root fs

no fstab.sys,mounting internal defaults.

Switching to new root and running init.

unmounting old /dev

unmounting old /proc

unmounting old /sys

6、  INITversion 2.86 booting

通过第五段来看,似乎对rootfs加入的写访问的支持。

于是我进行了如下测试:

grub.conf中修改:

kernel /vmlinuz-2.6.18-128.el5 ro root=/dev/sda2 vga=773 init=/bin/bash

目的是使启动进行到第6步时,暂停,并提供一个交互的shell

我通过shell执行:

df –h

/dev/sda3 …… /

 

mount

/dev/sda3 on / type ext3 (rw)

proc on /proc type proc (rw)

 

cat /etc/mtab

/dev/sda3 / ext3 rw 0 0

proc /proc proc rw 0 0

 

cat /proc/mounts

rootfs / rootfs rw 0 0

/dev/root / ext3 ro,data=ordered 0 0

/dev /dev tmpfs rw 0 0

/proc /proc proc rw 0 0

/sys /sys sysfs rw 0 0

 

此时的根文件系统是只读的,而且除了/分区(实际是/dev/sda2)被只读挂载外,其他的分区均没有被挂载(比如/boot,有可能在某些情况下(非正常关机)可以看得到其他分区被挂载的信息,但实际上挂载点内是空的)。所以可以认为:

1、  df mount命令查看的/etc/mtab当中的内容(是根据fstab来的)

2、  系统进行到这一步,还不涉及fstab

3、  真正挂载到根目录下的是/dev/root这个设备,挂载的参数是ro, data=ordered

 

接下来再继续系统的正常启动:

接上面的第6步:7.init(配置文件/etc/inittab àrc.sysinit(系统初始化脚本)àinitàrc(运行级别对应启动的服务和预执行的脚本)àinitàmingettyàloginàshell.

在系统初始化的过程中,看到:

Checking filesystems

/dev/sda3: ……

/boot: ……

Remounting root filesystem in read-write mode:

Mouting local filesystems:

Enabling local filesystems quotas:

Enabling /etc/fstab swaps:

 

到这里就关/etc/fstab的事了。查看rc.sysinit:

vim /etc/rc.d/rc.sysinit

……

# Remount the root filesystem read-write.

update_boot_stage RCmountfs

if remount_needed ; then

  action $"Remounting root filesystem in read-write mode: " mount -n -o remount,rw /

fi

……

关键就在这里了,因为此时的根文件系统是被挂载的,当执行”mount –n –o remount,rw /”,remount 这个参数并不会执umount的过程,只是更改了挂载的参数,而remount分区和挂载点对应的依据是fstab。这个时候,原本是/dev/sda2挂在/下的,没umount ,但一remount,和fstab里面的内容一匹配,好,乱套了。

注意,系统初始化的时候会依据fstab的最后一列的顺序对分区进行完整性检查(Checking)。如果这里出错的话,系统将无法启动,可以修复模式(Repair filesystem

 

为了验证上述判断,我将fstab中的/对应的的设备改为/dev/xxxx的错误形式,再启动。

果然在Checking的时候过不了,此时按ctrl+d将重启,输入root密码回车将进入Repair filesystem

说明不管正确与否,mtab都会记录fstab的挂载信息(尝试挂载过的),所以df mount命令就会读到不匹配的信息。

执行mount –o rw,remount /,报错,说没有这个设备,证明此操作会找fstab

执行mount –o rw,remount /dev/root / ,成功,根目录可写了,证明/dev/root就是根分区。其实通过查看设备号也可以知道:ls –l /dev/root  /dev/sda2,但两者是同一分区又不是同一设备文件,所以当/dev/root被挂载时,/dev/sda2没有挂载。

 

还是有问题解决不了,那就是当我在重复实验的时候,得到的结果会不一样了,有时候看到的/etc/mtab    里面是/dev/xxxx ,有时候是/dev/sda3, 有时候是/dev/sda2。当把mtab里面的内容清空,将/etc/fstab里面的写成/dev/xxxx,在修复模式下居然我所不能理解的是,mtab是怎样与fstab保持同步的?

 

做了最后一个实验:用init=/bin/bash将系统启动暂停,查看mtab内容,然后在修改fstab里的根文件系统的对应关系与现在的mtab不同,执行/etc/rc.d/rc.sysinit,查看mtab

得到如下结论:

启动时,在初始化之前,mtab里记录的内容与根文件系统上一次挂载的对应关系相同。在执行完rc.sysinit脚本后,则变成与fstab的内容相同。而实际的分区始终未变化。这样或许能解释上面的疑问。

看来,要确切的清楚细节,是需要看源码才行啊。

阅读(1411) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~