Kozupon.com    
 
 ディスクの構造とOSの起動!


OSの起動プロセスは、BIOSのロードから始まって、kernelのロード及びデバイスドライバーのロードまでを考えるとHDD上のデータ配置と密接に関係する。したがって、ディスクの構造も含め考えてみたい。


1.ディスクパーティション
PC/AT互換機の元々の仕様では、1つのハードディスクには、最大4つの基本パーティションを作ることが出来、さらに、基本パーティションの1つを拡張パーティションとして、その中を論理パーティションとしていくつでも区切ることが出来る。つまり、5つ以上パーティションが必要な場合は、必然的に拡張パーティションを利用することになる。例えば、Windowsを考えてみると、基本パーティションはCドライブのシステム領域で、アクティブにするブートパーディション(ブートセクター)もCドライブとなるので、基本パーティションを一つ作り、その他は拡張パーティションにして論理パーティションで複数に区切った方が効率的だ。
これらの基本・拡張パーティション情報は、ハードディスクの先頭セクターへ記録される。このセクターのことをMBR(Master Boot Record)と呼び、CD-ROMやFloppyDiskには無い構造である。
このMBRは1セクター(512バイト)の領域を有しており、MBRの後は62セクターの空きがあり、その後に基本パーティションが始まっている。
基本パーティションの先頭には、ブートセクター(1セクター分)が必ず配置される。さらに、拡張パーティションは、その中を論理パーティションに区切った、その先頭にEPBR(Extended Partition Boot Record)と言う論理パーティションの情報が記録されてる領域が作られる(図1参照)。


  図1


2.MBRはディスクの管理人
MBRの構造は、どうなってるのだろうか?実際に、Debina GNU/Linuxが入っているホストで検証してみる。

1)プログラム領域(446バイト)
ブートに関するプログラムが記録されている。インストールされているOSによって異なったブートプログラムが書き込まれている。

2)パーティションテーブル(64バイト)
ここには、基本・拡張パーティションに関する情報が記録されていて4つのエントリ構成になっている。
■パーティションの位置
■パーティションの種類
■アクティブフラグ(このパーティションからブートするかの判断フラグ)

3)ブートシグネチャ(2バイト)
これは、このMBRが正しい情報かの判断するための情報が書き込まれている。通常 0xAA55 になっていて、これ以外の値だと、BIOSはこのMBRを無効と判断する。

実際に、ハードディスクのMBRをファイルに保存してのぞいてみることにする。以下は、Debian GNU/LinuxのMBRをファイルへ保存して、そのファイルを16進ダンプしたものである。

wirehork:~# df -m
Filesystem 1M-blocks Used Available Use% Mounted on
/dev/hdc1 13782 1727 11356 14% /
tmpfs 126 0 126 0% /lib/init/rw
udev 10 1 10 1% /dev
tmpfs 126 0 126 0% /dev/shm

wirehork:~# fdisk -l -u /dev/hdc

Disk /dev/hdc: 15.3 GB, 15377080320 bytes
255 heads, 63 sectors/track, 1869 cylinders, total 30033360 sectors
Units = sectors of 1 * 512 = 512 bytes

Device Boot Start End Blocks Id System
/dev/hdc1 * 63 28676024 14337981 83 Linux
/dev/hdc2 28676025 30025484 674730 5 Extended
/dev/hdc5 28676088 30025484 674698+ 82 Linux swap / Solaris

wirehork:~# cd /tmp/

wirehork:/tmp# dd if=/dev/hdc bs=512 count=1 > mbr.dat
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000214844 seconds, 2.4 MB/s

wirehork:/tmp# hexdump -C mbr.dat
00000000 eb 48 90 6c 62 61 4c 49 4c 4f 01 00 15 04 5a 00  |詒.lbaLILO....Z.|
00000010 00 00 00 00 89 aa af 45 24 46 b0 00 00 25 46 b0  |.....・E$F握.%F淫
00000020 00 00 23 46 b0 00 00 01 70 65 27 46 b0 00 00 28  |..#F握..pe'F握.(|
00000030 46 b0 00 00 de 45 b0 00 00 df 45 b0 00 00 03 02  |F握.淌握.濺握...|
00000040 ff 00 00 20 01 00 00 00 00 02 fa 90 90 f6 c2 80   |??. ......??.??.|
00000050 75 02 b2 80 ea 59 7c 00 00 31 c0 8e d8 8e d0 bc  |u.荻袮|..1成悽仄|

省略

00000160 7c be 85 7d e8 40 00 eb 0e be 8a 7d e8 38 00 eb  ||小}萓.覡小}荼.譛
00000170 06 be 94 7d e8 30 00 be 99 7d e8 2a 00 eb fe 47  |.小}莪.小}茯.譫G|
00000180 52 55 42 20 00 47 65 6f 6d 00 48 61 72 64 20 44  |RUB .Geom.Hard D|
00000190 69 73 6b 00 52 65 61 64 00 20 45 72 72 6f 72 00  |isk.Read. Error.|
000001a0 bb 01 00 b4 0e cd 10 ac 3c 00 75 f4 c3 00 00 00  |皿.堪柚・.u??...|
000001b0 00 00 00 00 00 00 00 00 90 90 90 90 90 80 80 01  |................|
000001c0 01 00 83 fe ff ff 3f 00 00 00 7a 8f b5 01 00 fe    |...????...z.貴.??
000001d0 ff ff 05 fe ff ff b9 8f b5 01 54 97 14 00 00 00    |??.????.貴T.....|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa  |..............U・

上のデータで、初めの446バイトまで(0x0000〜0x01BD迄)がプログラム領域で、ここを見るとこのLinuxシステムのブートローダーはGRUBが使われていることがわかる。しかし、初めの方でLILOと書き込まれているのは、更新前のブートローダーがLILOを使っていて、その残骸のようだ。

↓データの抜粋

000001b0                           80 01    |................|
000001c0 01 00 83 fe ff ff 3f 00 00 00 7a 8f b5 01 00 fe    |...????...z.貴.??
000001d0 ff ff 05 fe ff ff b9 8f b5 01 54 97 14 00 00 00    |??.????.貴T.....|
000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa  |..............U・

上のデータで、先頭が0x80なので、この場合はアクティブパーティションになっている。次にパーティションテーブルのエントリー1の開始位置がリトルインディアン(数値データを1バイト単位で区切ったとき、会の桁から読み書きする方式)読みで0x000101(01 01 00)は、シリンダ0、セクター1、ヘッド1、つまり第2トラックとなる。

80 01 01 00 83 fe ff ff   3f 00 00 00 7a 8f b5 01  →   エントリー1
00 fe ff  ff 05 fe ff ff   b9 8f b5 01 54 97 14 00  →   エントリー2
                                    55 aa  →   ブートシグネチャ

元々、MBRはシリンダ0、セクター1、ヘッド0の1セクターのみの領域であるため、残りのシリンダ0、ヘッド0の領域(セクター2〜セクター63迄)は何も使われてない空き領域となる。何だかもったいない気もするが、PC/AT互換機の仕様では、第1パーティションは第2トラックから始まらなければいけない仕様になっているようだ。さらに、パーティションタイプは、上記のエントリー1に0x83が書き込まれているので、第1パーティションはLinux Native(ext3)、エントリー2に0x05が書き込まれているので、第2パーティションは拡張パーティションを表している。
また、同じく上記のエントリーに対して、LBAアドレッシングでのパーティション開始位置とパーティションの総セクター数を見てみると、第1パーティションの開始位置は0x0000003F(63)、総セクター数は0x01B58F7A(28675962)、第2パーティション開始位置は0x01B58FB9(28676025)、総セクター数は0x00149754(1349460)となっている。
最後に、0xAA55でブートシグネチャで、このMBRは正しいものである、と言っている。
上記のMBR情報では、基本パーティション(MAX4つ)だけしか記録されない。と言うのも、拡張パーティション内の論理パーティション(いくつでも作れる)情報はMBRではわからない。そこで、論理パーティション情報を知るために、EPBR(Extended Partition Boot Record)と言う拡張パーティション内の先頭1セクターの情報を見てみよう。構造的には、MBRと全く同様である。

wirehork:/tmp# dd if=/dev/hdc2 bs=512 count=1 > ebr.dat
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0189323 seconds, 27.0 kB/s

wirehork:/tmp# hexdump -C ebr.dat
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
*
000001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe  |...............??
000001c0 ff ff 82 fe ff ff 3f 00 00 00 15 97 14 00 00 00    |??.????.........|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa  |..............U・
00000200

↓データ抜粋

                                 00 fe    |...............??
000001c0 ff ff 82 fe ff ff 3f 00 00 00 15 97 14 00 00 00    |??.????.........|
000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |................|
*
000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa  |..............U・

00 fe ff ff 82 fe ff ff 3f 00 00 00 15 97 14 00   →  エントリ1
                                 55 aa   →  ブートシグネチャ

上のデータで第1論理パーティションタイプが0x82が書き込まれているので、LinuxSwap・Solarisを表している。さらに、パーティション開始位置は0x0000003F(拡張パーティションの先頭から63)で、総セクター数は0x00149715(1349397)となる。そして、最後にブートシグネチャがあって、このEPBRは正しいものである、と言っている。


3.BIOSのお仕事
図2は、BIOSの仕事の流れである。PC/AT互換機では、電源を入れてから、まず初めに起動させるプログラムが有る。それは、BIOS(Basic Input/Output System)である。BIOSは、PCの中にあらかじめ用意されている。BIOSは必要最小限の小さなプログラムだ。当たり前だが、BIOSでは自分がどのようなOSでどんなファイルシステムであるかまではわらないが、デバイスへの物理的なアクセスは出来るので、セクター番号を指定して、有るセクターのデータをメモリへロードすることは可能である。つまり、デバイスというデバイス全てに対して、BIOSのプログラムだけでセクターリードが可能だ。
では、早速、BIOSの仕事を見てみよう。まず、BIOS自体をメインメモリへロードする。ロードしたBIOSが実行される。BIOSが実行されたら、CPU周りのメモリ、IO等の自己診断テストを行う(例えば、メモリではあるデータを全ての番地へ書き込み・読み込みを繰り返す)。
次に、ハードディスク・FDD・ストレージ・グラフィックボード・キーボード等のデバイスの初期化を行う。例えば、起動デバイスにハードディスクが設定されている場合などは、ハードディスクの先頭セクター(MBR)をリードして、510 バイト目のブートシグネチャをチェックしに行く。前項で説明したように、ブートシグネチャが正しい値(0xAA55)だった場合、先頭セクターに書き込まれている起動プログラムをキックする。また、そうでなければ、次に設定された起動ドライブをリードしに行く。さらに、全てのドライブでリードが行えないとすると、エラーとなりPCはHALT(停止)状態になる(図2参照)。


  図2

ハードディスクからの起動の場合、MBRのプログラム領域に書き込まれているプログラムは、ブートストラップと言いLinuxで言うとGRUBのようなプログラムを言う。通常ブートストラップは、ドライブのアクティブなパーティションの先頭番地からロードするようになっている。パーティションの先頭にはIPL(Initial Program Loader)が設置してあり、OSのコアシステムをロードする。つまり、Linuxで言うとカーネルがロードされるわけである。
以上


 
 
 



Copyright 2007 Kozupon.com.