1. 程式人生 > >MBR結構解析與fdisk的bash實現

MBR結構解析與fdisk的bash實現

一行 star padding aid htm loader IT height file

一、MBR結構解析

首先我們先介紹一些MBR的基本知識基礎,再晾圖片分析。

MBR主要分為三大塊各自是:

1、載入引導程序(446K)

2、分區表(64k)

3、標誌結束位(2k)

載入引導程序:內容是因機器而異它裏面正如其名。就是存放載入引導程序。如今基本的載入引導程序是LILO(LInux LOader)和 GNU GRUB(GRand Unified Boot loader)。

分區表:裏面主要記錄4個16K主分區的信息。我們將在下文進行具體介紹。

表示結束位:就是標誌MBR結束。通常是0xaa55。

假設不是。則告訴機器前面的內容是不合法的。

然後我們運行以下的命令一起來看看MBR內容:

# dd if=/dev/sdb bs=512 count=1 | hexdump -C

技術分享圖片

要看懂上圖,我們得復習一下組成原理的基本知識。(1字節=1B=8二進制位=2個十六進制位)

然後上圖中,左側第一列是偏移量。因為每一行的數據是16k,所以每行偏移量0x10。

依據我們上面的介紹,載入引導程序是446k、分區表是64k、標誌結束位是2k。所以正如上圖黑色區域和白色區域標誌一樣。我們得到了相應每一個區域的範圍例如以下:

載入引導程序:(00000000 第1字節~000001b0 第14字節)

分區表:(000001b0 第15字節~000001f0第14字節)

標誌結束位:(000001f0第15字節~000001f0第16字節)

註:此處沒有第0字節


因為分區表包涵了我們須要的大部分信息。接下來我們重點解析一下分區表。

000001b0? 00 00 00 00 00 00 00 00? c8 87 da 95 00 0080 01

000001c0? 01 00 07? fe?? ff?? ff?? 3f? 00? 00 00 06 73 41 06 00 fe

000001d0?? ff?? ff?? 0f?? fe?? ff?? ff?? 45 73? 41 06 bb 5c 01 1f00 00

000001e0? 00 00 00 00 00 00 00? 00 00 00 00 00 00 0000 00

000001f0?? 00 00 00 00 00 00 00 00? 00 00 00 00 00 0055 aa

上圖中,我們為4個分區的內容分別標上了不同顏色。

我們為了方便解析每一個字段,以第一個分區為樣例。而且為每一個字節分配一個名字。具體例如以下:

80 01 01 00 07 fe ff ff 3f 00 00 00 06 73 41 06
status
f1 f2 f3 parttype
l1 l2 l3 lba1 lba2 lba3 lba4 s1 s2 s3 s4

盡管看起來非常多,但事實上僅僅有幾類:

status:是否是可啟動盤是的話就是0x80。否則就是0x00

f3+f2+f1:分區的開始位置

l3+l2+l1:分區的結束位置

s4+s3+s2+s1:分區的大小

parttype:分區類型。在fdisk中能夠查看得到相應列表例如以下圖。我這裏第一個分區是07類型,也就是HPFS/NTFS的windows文件系統。第二個分區才是Linux。

技術分享圖片

二、fdisk驗證

我們以第一個主分區為樣例對某些字段進行簡單的驗證,下圖是fdisk /dev/sdb的結果

技術分享圖片

Boot:第一個字節0x80說明第一個分區是可啟動分區

Id:也就是parttype字段相應的值是0x07

System:依據id從fdisk的表格中得到HPFS/NTFS文件系統

Blocks:這裏是s4s3s2s1=0x06417306,我們相同利用 echo "ibase=16;06417306/2" | bc 得到52476291k也剛好驗證了上面的數值。

Start:這裏f3f2f1=0x000101。我們利用echo “ibase=16;000101/2” | bc 得到128k。這裏為什麽是128k而不是上文fdisk中的1呢?主要是因為兩個問題造成,第一個是fdisk的end和start中的數值是指磁盤的柱面。

所以並非簡單的kB或者MB,因為依據磁盤型號不同,它每一個柱面的大小容量也是不一樣的。

此外第二個原因是這裏可能是因為磁盤的stripe造成的。

RAID卡配置--stripe size在每一個磁盤上連續寫入數據的總量,也稱作“條帶深度”。)stripe一般默認是128k。可能因為預設的原因所以不是從柱面0開始,而是從1開始。

(註:硬盤容量 =柱面數(表示每面盤面上有幾條磁道,一般總數是1024) ×磁頭數(表示盤面數) ×扇區數(表示每條磁道有幾個扇區,一般總數是64)× 扇區(存儲基本單元,大小一般為512B/4KB))

三、fdisk的bash實現

?????? 前些實習的日子,找到了一個比較優美的bash代碼。

是檢測MBR的啟動分區、分區類型、大小等信息。這些信息也就是從我們上面介紹的分區表中得到。這裏把代碼拿出來,盡管有用性上不強(畢竟已經有fdisk)。可是拿出來一起學習。假設有不好的地方請指正哈。

#!/bin/bash
if [ -b $1 ];then
	mbr=`mktemp`
	echo "Reading MBR from device $1"
	dd if=$1 of=$mbr bs=512 count=1
	mbr_is_temporary=1
else
	mbr=$1
	if [ -r "$mbr" ];then
		echo "Reading MBR from file $mbr"
	else
		echo "Readable MBR required."
		exit 1
	fi
fi

od -v -t x1 -An -j 510 $mbr | grep -q " 55 aa$"
if [ "$?" -ne "0" ];then
	echo "MBR signature not found.Not a valid mbr."
	exit 1
fi

partmun=1
od -v -t x1 -An -j446 -N 64 $mbr | while read status f1 f2 f3 parttype l1 l2 l3 lba1 lba2 lba3 lba4 s1 s2 s3 s4
do
	if [ "$parttpye" == "00" ];then
		echo "Partition $parttpye is not defined"
	else
		case $status in
			00) bootable="unbootable";;
			80) bootable="bootable";;
			*) bootable="invail";;
		esac
		printf "Partiton %d is type %02s and is %s." $partnum $parttype $bootable
		sectors=`printf "%02s%02s%02s%02s\n" $s4 $s3 $s2 $s1 | tr ‘[:lower:]‘ ‘[:upper:]‘`
		bytes=`echo "ibase=16; $sectors / 2" | bc`
		gb=`echo "scale=2; $bytes / 1000 / 1000" | bc`
		printf " Size %.02f GB \n" $gb
	fi
	partnum=`expr $partnum + 1`
done
if [ "$smb_is_temporary" ];then
	rm -f $mbr
fi


實現效果:

技術分享圖片

MBR結構解析與fdisk的bash實現