免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
1234下一页
最近访问板块 发新帖
查看: 29810 | 回复: 34

[FreeBSD] FreeBSD的磁盘分区 [复制链接]

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-06-30 16:04 |显示全部楼层
上面雨丝风片结合bochs的汇编调试器详细描述了mbr的引导过程。作为上文的延续,这里我和大家一起用基于实验的手法观察PC机上FreeBSD的分区。

FreeBSD在PC结构的计算机上,有两种同时使用的,也是十分容易混淆的分区概念:一是DOS分区,一是BSD分区。本文的重点在帮助大家准确理解这两种分区。

为了理解分区,我们最好的插手阶段是FreeBSD的引导过程。简单的说,完整的FreeBSD的引导分为四部分:第一部分是DOS分区的mbr引导,FreeBSD将之称为boot0;第二部分是FreeBSD分区的引导,FreeBSD将之称为boot1;然后是FreeBSD所谓的boot2引导,最后是loader引导。


整个过程如下图1示
图1:引导过程简图

图1:引导过程简图

图1:引导过程简图


其中mbr引导是与FreeBSD无关的,也就是说我们可以使用很多不同的引导工具进行mbr引导,最著名的恐怕就是grub了。后面三个引导阶段是FreeBSD自有的,这是FreeBSD称之为三部曲的引导,本文仅解析磁盘分区,并不深入FreeBSD的引导,因此关于boot的详情可以参见man 8 boot。


第一部分:DOS分区

那么,奇怪的是为什么在讨论FreeBSD分区的时候,我们需要首先面对的却是DOS分区呢?原因在于,PC机上的FreeBSD运行在基于IA32的硬件之上,并且在设计时就考虑到和同一个磁盘上的其他系统共存的用户需求,比如Microsoft Windows。所以,FreeBSD不得不建立在DOS分区之上的。当然运行在非IA32体系的计算机上的FreeBSD系统并不一定使用DOS分区。

首先我们需要一个实验环境来观察后面的操作:操作系统FreeBSD7.0-release,虚拟机bochs2.3.7,虚拟磁盘大小10G,分为两个区:一个分区1G为FAT分区,另一个分区9G为BSD分区。创建虚拟磁盘的操作显示如图2:

图2: 实验用虚拟硬盘

图2: 实验用虚拟硬盘

图2: 实验用虚拟硬盘


图2告诉我们的最重要的信息是total sectors=20971440,而我们在安装*BSD时经常看到的cylinder=20805,heads=16等信息在现在较新的磁盘上已经不再重要,至于原因我们放在下面讲述。我们还可以看出这个磁盘的扇区大小为(10239.96MB/20971440扇区=512字节)。

空白磁盘添加了保留引导区之后的第一次划分光秃秃的如下图3:

图3: 磁盘的第一次划分

图3: 磁盘的第一次划分

图3: 磁盘的第一次划分


这时磁盘上并没有任何数据,这63个扇区的划分直到后面写入磁盘信息时才会正式建立,我们这里引用这些分区是为了文章描述的逻辑性。

OK,接下来我们正常安装FreeBSD,直到下一步,如图4:(同样的信息我们也可以在系统安装完成之后使用fdisk命令查看)

图4中显示了设备名:ad0,整个磁盘扇区大小:20971440,还有三个看起来像分区的条目。呃,这里用了“看起来像”,是因为从扇区0到扇区62结束的第一个条目,其实不是一个分区,它是磁盘的保留块,至于为什么要63个扇区而不是我们经常讲的mbr 1个扇区?原因在于磁盘开始的63个扇区保留给了mbr和扩展分区。而为什么保留的扇区是63而不是64,65呢?呃,因为一个柱面包含了63个扇区 第0个扇区确实是我们关心的mbr,而第1—62扇区,是为扩展分区保留的空间,它可以不使用。如果是这样,那么1—62扇区可以存放扩展引导代码,也可以放数据。

进一步划分:一个分区1G为FAT分区,从63扇区开始到2096639扇区结束,共(2096639−63+1) = 2096577个扇区,共2096577S · 512B = 1023KB = 1G。这个分区的分区号为Subtype = 6。另一个分区9G为FreeBSD分区,从2096640扇区开始到20971439扇区结束,共18874800个扇区,分区号为Subtype = 165。

图4: 划分磁盘DOS分区

图4: 划分磁盘DOS分区

图4: 划分磁盘DOS分区


图4中显示的Subtype也就是我们通常说的分区类型,我们会在后面的mbr实例中看到这个类型号。然而,分区类型的使用只与操作系统有关。系统挂载时,OS可以使用,也可以不使用这个类型决定目标分区系统的类型。

接下来的安装中,用户可以选择FreeBSD安装到mbr的操作类型,如图5所示。

图5: mbr引导程序选择

图5: mbr引导程序选择

图5: mbr引导程序选择


BootMgr对应/boot/boot0(代码在src/boot/i386/boot0/),Standard对应/boot/mbr(代码在src/boot/i386/mbr/),None当然就是不改变当前PC机安装的mbr。那么问题是:FreeBSD为什么要分两种类型的mbr?其实boot0和mbr都是安装在PC机的mbr上的,完成相同的引导功能,然而它们之间的区别在于boot0提供一种简单的分区选择功能。当系统启动时,boot0会根据分区表的内容自动检测系统上存在的磁盘分区,然后在一定计时范围内给出一个选择让用户自行选择boot0下一步引导的磁盘分区。这时可以看见屏幕上出现的所有分区列表,和它对应的选择键:F1, F2, F3等等。用户如果在这期间选择了一个分区进行引导,那么boot0自动将用户选择的分区激活为活动分区并进行加载。当计时超出之后,boot0将默认选择分区表中记录的活动分区进行引导。这样一来,如果上一次用户选择了某个分区进行引导,那么下一次PC机启动的时候,默认的启动分区就是上一次用户选择的引导分区。

/boot/mbr的功能就简单的多,只需要找到分区表里面的活动分区进行加载就完成任务。具体的代码分析参见雨丝风片的FreeBSD7.0 /sys/boot/i386/mbr/mbr.s源代码分析。

需要注意的是:我们这里仅仅只是引用文件系统上的对应特定文件,这并不意味着系统引导之时,就是执行的这些文件。也就是说:FreeBSD在引导过程中执行的boot0(mbr) 和后面讲述的boot1 都不是直接执行文件系统上的代码。因为在引导之时,FreeBSD的文件系统结构尚未在内存中建立。解决的办法是通过bsdlabel, boot0cfg等工具,FreeBSD直接将/boot/boot0(/boot/mbr) 和/boot/boot1 安装到磁盘的对应扇区上(需要root权限)。

图6: mbr结构,图片来自wiki

图6: mbr结构,图片来自wiki

图6: mbr结构,图片来自wiki

图6和图7显示了mbr的结构和分区表结构,下面祭起我们的照妖镜 -- bochs,观察有关分区的系统活动。

图7: mbr分区结构,图片来自wiki

图7: mbr分区结构,图片来自wiki

图7: mbr分区结构,图片来自wiki


中间插一句(等会还要继续按照我们的系统,呵呵),在整个系统安装完成之后,我们通过在bochs引导初期下断点的方式,取得图8所示的整个512字节mbr反汇编:

图8: mbr中的分区表

图8: mbr中的分区表

图8: mbr中的分区表


mbr信息我们也可以通过dd if=/dev/ad0 of=mbr.bin bs=512 count=1得到(为什么是/dev/ad0在后面解释)。我们最关心的是446—509字节表示的mbr分区表内容,每个条目16字节,共4个条目。446—462字节描述了第一个DOS分区,463—479描述了第二个DOS分区。

0x7DBE开始的16个字节依次是00 010100 06 0fffff 3f000000 c1fd1f00(注意,这里反汇编显示的是intel的little-ending序)按照图7的分区表格式,我们知道这个分区不是引导分区(0x0),分区类型是0x6 (图4中的Subtype域,下同),起始LBA在第0x3f=63 扇区,分区大小0x1ffdc1=2096577 扇区,这是一个FAT分区。继续0x7DCE开始的第二个分区,依次是80 ffffff a5 0fffff 00fe1f00 b0012001 按照图7的分区格式,这个分区是引导分区(0x80),分区类型是0xa5 (表示FreeBSD分区),起始LBA在第0x1ffe00=2096640扇区,分区大小0x12001b0=18874800 扇区,这是一个FreeBSD分区。

呵呵,是不是和我们在图4中看到的一样呢?至此,FreeBSD引导过程的DOS引导部分完成。

总结一下目前为止的DOS分区的情况,图9


图9: 简明DOS分区结构

图9: 简明DOS分区结构

图9: 简明DOS分区结构


整个第一个磁盘在FreeBSD里面表示为/dev/ad0,如果有第二个磁盘,则命名为/dev/ad1,依次类推。磁盘上的DOS分区在FreeBSD里面表示为Slice,因此第一个磁盘/dev/ad0上的第一个Slice为/dev/ad0s1,第二个Slice为/dev/ad0s2。正如9所示,/dev/ad0s1在mbr里面被表示为FAT分区,从63号扇区开始到2096639扇区结束;/dev/ad0s2在mbr里面被表示为FreeBSD分区,跨越剩下的磁盘空间。

最后做个简单的加法:
/dev/ad0s2 = /dev/ad0 + 2099640 。
这意味着
dd if=/dev/ad0s2 of=xxx bs=512 count=1

dd if=/dev/ad0 of=yyy bs=512 count=1 skip=2099640
完成相同的功能。


[ 本帖最后由 gvim 于 2008-6-30 16:55 编辑 ]

评分

参与人数 2可用积分 +7 收起 理由
BruceShea + 2 原创内容,好文章!
雨丝风片 + 5 精品文章

查看全部评分

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-06-30 16:04 |显示全部楼层
接上


第二部分:FreeBSD分区

我们继续前面的安装过程,进行到下步图10:
图10: BSD分区

bsdpart.JPG


这里我们同样看到了/dev/ad0s1和/dev/ad0s2的区分信息。我们在FreeBSD中分三个分区,第一个128M作为swap,接着是1G的/根,最后剩下的都分给/usr。默认剩下的操作步骤,就可以将FreeBSD系统安装到bochs虚拟机中,下面的实验操作(以及上面提及的相关操作都可以在完整系统中实验了)。

那么BSD分区结构又是什么样的呢,它在磁盘上的布局又是怎样?

首先源代码src/sys/sys/disklabel.h中的struct disklabel结构告诉了我们关于BSD分区结构的答案(分区类型号也记录在这个文件里)。

简单起见,我们只引用本文关心的结构域和分区类型:

  1. #define MAXPARTITIONS 8
  2. struct disklabel {
  3.         u_int32_t d_magic; /* the magic number */
  4.         char d_typename[16]; /* type name, e.g. "eagle" */
  5.         struct partition { /* the partition table */
  6.                 u_int32_t p_size; /* number of sectors in partition */
  7.                 u_int32_t p_offset; /* starting sector */
  8.                 u_int8_t p_fstype; /* filesystem type, see below */
  9.         } d_partitions[MAXPARTITIONS]; /* actually may be more */
  10. };

  11. #define FS_UNUSED       0               /* unused */
  12. #define FS_SWAP         1               /* swap */
  13. #define FS_V6           2               /* Sixth Edition */
  14. #define FS_V7           3               /* Seventh Edition */
  15. #define FS_SYSV         4               /* System V */
  16. #define FS_V71K         5               /* V7 with 1K blocks (4.1, 2.9) */
  17. #define FS_V8           6               /* Eighth Edition, 4K blocks */
  18. #define FS_BSDFFS       7               /* 4.2BSD fast filesystem */
  19. #define FS_MSDOS        8               /* MSDOS filesystem */
  20. #define FS_BSDLFS       9               /* 4.4BSD log-structured filesystem */
  21. #define FS_OTHER        10              /* in use, but unknown/unsupported */
  22. #define FS_HPFS         11              /* OS/2 high-performance filesystem */
  23. #define FS_ISO9660      12              /* ISO 9660, normally CD-ROM */
  24. #define FS_BOOT         13              /* partition contains bootstrap */
  25. #define FS_VINUM        14              /* Vinum drive */
  26. #define FS_RAID         15              /* RAIDFrame drive */
  27. #define FS_JFS2         21              /* IBM JFS2 */

复制代码


d_magic表示分区的幻数,BSD的分区幻数表示为:0x82564557。d_packname是分区所在的磁盘标识符,也就是引用它的设备名。d_partitions中的p_size代表分区长度,p_offset代表起始扇区号,p_fstype表示分区类型。

FreeBSD系统正常安装之后,通过bsdlabel命令我们看到下面的BSD分区结构图11:

图11: BSD分区结构

图11: BSD分区结构

图11: BSD分区结构


那么BSD分区是如何在磁盘上分布的呢?图12显示出一个最一般的FreeBSD分区的磁盘分布。

图12: BSD分区磁盘分布

图12: BSD分区磁盘分布

图12: BSD分区磁盘分布


注意,这里的扇区号是相对/dev/ad0s2的扇区号。因此0,1,. . .,15,16等相对扇区需要在整个磁盘上引用的话,需要加上/dev/ad0s2的绝对起始扇区,也就是2096640。

简单解释一下这个图:在我们的实例系统里,FreeBSD分区的前128个扇区(64k)作为FreeBSD本身的引导区,后面接着是文件系统超级块,柱面组信息等等,这里就不详述了。其中第二个扇区开始的sizeof struct disklabel = 276个字节存放的是BSD分区表信息,这是我们这里的重点。围绕第二个扇区的其余十五个扇区,是FreeBSD的引导代码。。。(可恶,怎么又出来一个引导说-_-;),在图12中的boot1和boot2都是FreeBSD的引导代码,至于它们怎么一起工作,这里也不再关注(以后专文呈诉)。

为什么强调“我们的实例系统里”?因为FreeBSD的引导扇区并不固定为64K,还有其他尺寸可以选择,而我使用的刚好是最通常的情况:64K。

前面我们成功的从mbr里面找到了FreeBSD分区的起始扇区号:2096640。/boot/mbr读取2096640扇区的内容,正式进入FreeBSD系统的引导三部曲(man 8 boot)。

那么2096640扇区存放的是什么让我们感兴趣的东西呢?很容易从man 8 boot中找到信息:FreeBSD分区的第一个扇区存放的是boot1,图12中的第一部分。可以通过命令
dd if=/dev/ad0s2 of=boot1.bin bs=512 count=1
得到这个引导块。

紧接着的磁盘块是我们的目标,呃,很简单,用命令
dd if=/dev/ad0s2 of=bsdlabel.bin bs=512 count=1 skip=1
就取得了。用十六进制编辑器查看bsdlabel.bin这个文件的前276 个字节:


00000000  57 45 56 82 05 00 00 00  61 64 30 73 32 00 00 00  |WEV.....ad0s2...|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 02 00 00 3f 00 00 00  |............?...|
00000030  10 00 00 00 45 51 00 00  f0 03 00 00 b0 ff 3f 01  |....EQ........?.|
00000040  00 00 00 00 00 00 00 00  10 0e 01 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000080  00 00 00 00 57 45 56 82  f3 96 08 00 00 20 00 00  |....WEV...... ..|
00000090  00 00 00 00 00 00 20 00  00 fe 23 00 00 08 00 00  |...... ...#.....|
000000a0  07 08 88 6f 00 00 04 00  00 fe 1f 00 00 00 00 00  |...o............|
000000b0  01 00 00 00 b0 01 20 01  00 fe 1f 00 00 00 00 00  |...... .........|
000000c0  00 00 00 00 b0 01 fc 00  00 fe 43 00 00 08 00 00  |..........C.....|
000000d0  07 08 88 6f 00 00 00 00  00 00 00 00 00 00 00 00  |...o............|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000110  00 00 00 00


结合struct disklabel的结构域,我们清楚的看到:d_magic = 0x82564557,d_typename = da0s2,第一个BSD分区的分区信息从0x94字节偏移开始共16字节。前面8个字节是p_size = 0x200000 = 2097152个扇区,p_offset = 0x23fe00 = 2358784号扇区,p_fstype = 0x07。

咦,怎么回事,offset居然跑那么远?嗯,不要忘记了还要算上/dev/ad0s2的绝对偏移:2096640 + 262144 = 2358784。这样就对了,我们在图11中看到这个分区就是分区'a',在FreeBSD里面表示“/” 根分区,表示为/dev/ad0s2a,由于这个条目在bsdlabel中是第一个条目,所以就是'a'咯。类型号0x07经过查表,知道这个分区表示FS_BSDFFS。

然后下面的第二个条目,类推当然就是'b':/dev/ad0s2b,大小为0x40000 = 262144 个扇区,绝对偏移为0x1ffe00 = 2096640号扇区。相对于/dev/ad0s2的启示扇区,这个相对偏移当然就是0(图11中的offset域)。类型号0x01,表示FS_SWAP。

下面的第三个和第四个条目,可以用相同的方法推知。需要特别说明的是,'c' 在BSD分区里面表示整个Slice。

bingo!通过我们的分析,得到了和图11完全一致的结果

最后,说了这么多,终于可以总结DOS分区和BSD分区的关系:

图13: 磁盘上的分区总览

图13: 磁盘上的分区总览

图13: 磁盘上的分区总览


[ 本帖最后由 gvim 于 2008-7-1 09:50 编辑 ]

评分

参与人数 1可用积分 +5 收起 理由
雨丝风片 + 5 精品文章

查看全部评分

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2008-06-30 17:12 |显示全部楼层
不错,最近越玩越高深了啊

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
发表于 2008-06-30 17:20 |显示全部楼层
继续学习

感谢分享

论坛徽章:
0
发表于 2008-06-30 17:35 |显示全部楼层
好文,支持GVIM老兄

论坛徽章:
2
亥猪
日期:2014-03-19 16:36:35午马
日期:2014-11-23 23:48:46
发表于 2008-06-30 17:35 |显示全部楼层
对了,忘了补一句“cylinder=20805,heads=16等信息在现在较新的磁盘上已经不再重要”,意味着现在较新的磁盘使用的线性扇区寻址,大概来说就是LBA(Logic Block Address),不再用这些柱面,磁头等东西寻址啦。
忘说了

[ 本帖最后由 gvim 于 2008-6-30 17:36 编辑 ]

论坛徽章:
0
发表于 2008-07-01 09:31 |显示全部楼层
非常感谢!希望BSD版多出这样的好贴

论坛徽章:
0
发表于 2008-07-01 11:08 |显示全部楼层
经典好文,看完之后对freebsd硬盘分区的概念清晰多了。

论坛徽章:
1
寅虎
日期:2013-09-29 23:15:15
发表于 2008-07-01 11:09 |显示全部楼层
好贴!支持!!

论坛徽章:
2
丑牛
日期:2013-09-29 09:47:222015七夕节徽章
日期:2015-08-21 11:06:17
发表于 2008-07-01 11:10 |显示全部楼层
不错不错,收藏了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP