一个硬盘可以有很多分区,但MBR分区表只有四项,怎么能突破这个限制呢?答案是扩展引导记录(EBR - Extended Boot Record),通过把MBR分区表中一项设为扩展分区(系统ID为0x05或0x0F),其分区表项指定扩展分区的起始位置和长度,在其中最开始扇区 (EBR)和MBR相同位置(0x1BE)放置另外一个分区表,一般称为扩展分区表。扩展分区表的第一项指定扩展分区目前的逻辑分区信息,如果还有更多的 逻辑分区,扩展分区表的第二项指定下一个EBR的位置,否则为0。最后的两个分区表项总是为0。通过这种方式,一个硬盘上的分区数目就没有限制了。
以上的意思即是说,扩展分区是MBR表项中的4个分区表中的一个分区表,而扩展分区又通过一个链式的分区表将多个逻辑分区进行管理。即逻辑分区是扩展分区中的一部分,是子的位格。
注意:在逻辑分区中,每个分区只是前两个分区表的信息有用,后两个分区表未使用,所以以下程序并没有进行3 4个分区信息的读取。
那么如何读取扩展分区中的多个逻辑分区的分区表呢?
int Ext2Read::scan_ebr(FileHandle handle, lloff_t base, int sectsize, int disk)
{
unsigned char sector[SECTOR_SIZE];
struct MBRpartition *part, *part1;
Ext2Partition *partition;
int logical = 4, ret;
lloff_t ebrBase, nextPart, ebr2=0;
//表示此扩展分区开始的首扇区的相对扇区号(应该是相对于上一个分区吧)
ebrBase = base;
nextPart = base;
while(1)
{
//读取此逻辑分区的第一个扇区
ret = read_disk(handle, sector, nextPart, 1, sectsize);
if(ret < 0)
return ret;
if(ret < sectsize)
{
printf("Error Reading the EBR \n");
return -1;
}
//得到当前逻辑分区的分区信息,偏移446字节
part = pt_offset(sector, 0);
printf("index %d ID %X size %Ld \n", logical, part->sys_ind, get_nr_sects(part));
//若文件系统为EXT2则进行处理,记录此分区的总扇区数,当前分区相对扇区号,扇区大小,设备控制句柄。
if(part->sys_ind == EXT2)
{
partition = new Ext2Partition(get_nr_sects(part), get_start_sect(part)+ ebrBase + ebr2, sectsize, handle, NULL);
if(partition->is_valid)
{
//为什么logical的初值为4,因为逻辑分区的分区号是从5开始的,在set_linux_name函数中将进行变化为+1
partition->set_linux_name("/dev/sd", disk, logical);
//将ext2分区的对象存入到ext2有效分区列表中
nparts.push_back(partition);
}
else
{
delete partition;
}
}
//对分区为lvm的分区的处理
if(part->sys_ind == LINUX_LVM)
{
printf("LVM Physical Volume found disk %d partition %d\n", disk, logical);
LVM lvm(handle, get_start_sect(part)+ ebrBase + ebr2, this);
lvm.scan_pv();
}
//得到下一个逻辑分区的分区信息,下一个逻辑分区信息是在当前逻辑分区表的第二个分区表中;
part1 = pt_offset(sector, 1);
//得到当前分区的开始扇区相对扇区号(应该是相对于上一个分区的)
ebr2 = get_start_sect(part1);
//累加得到当前分区的开始扇区的相对扇区号
nextPart = (ebr2 + ebrBase);
//累加得到分区的个数
logical++;
//如果逻辑分区表中的第二个表的文件系统为0,则表示已经没有逻辑分区了
if(part1->sys_ind == 0)
break;
}
return logical;
}