JF-INDEX (document list of JF Project)

ハードディスクドライブの基礎知識

佐野武俊 / Taketoshi Sano, (kgh12351@nifty.ne.jp)

$Date: 1999/12/05 03:17:15 $, ($Revision: 1.4 $)


ハードディスクドライブの「ジオメトリー」と「パーティション」について 簡単に説明するために、いくつかの参考文献などからの情報をまとめたものです。 内容および文書の構成についての御意見をお待ちしております。

1. ハードディスクの「ジオメトリー」とは ?

2. ディスクアクセス

3. パーティションについて

4. おわりに


1. ハードディスクの「ジオメトリー」とは ?

現在、一般的に使われているハードディスクドライブ (以下 HDD) の 「ジオメトリー」は、 C/H/S (シリンダー数、ヘッド数、セクター数) の 3 つの数値から構成されます。もともとこれらの数値の組み合わせは、 HDD の構成を示す情報として物理的な意味、つまり以下のような意味を 持つ数値でした。

1.1 シリンダー

ディスク上に存在するトラック (後述) を、その位置 (トラック番号) に よって分類したもの。ドライブ中に複数のディスクが存在する場合、同じ トラック番号 (シリンダー位置) に対応する各トラックを結ぶと円筒上に並ぶこと からこの名称があるようです。一般にドライブ中の各ディスク上に存在する トラックの本数は同じであり、「HDD のジオメトリー」として使われる 「ドライブのシリンダー数」とは「各ディスク上のトラック数」のことです。

1.2 トラック

1 枚のディスク上に多数存在している同心円状の円周のひとつひとつ を指します。このトラック上に情報をビット単位で記録する磁気媒体が 並んでいます。ディスクの回転によってトラック上を磁気ヘッドが移動し、 情報の書き込み/読み出しを行ないます。

1.3 ヘッド

媒体へ情報を記録したり、媒体から情報を読み取ったりするために 使われるドライブ中の磁気ヘッド。ひとつのドライブ中に複数の ディスクが存在したり、ひとつのディスクの裏表にヘッドが存在する などの理由によって、たいていのドライブには複数のヘッドが存在 しています。 「HDD のジオメトリー」として使用される「ドライブのヘッド数」とは そのまま「ドライブ中に存在する磁気ヘッドの個数」だと思っておいて 良いでしょう。

最近の HDD はボイスコイルでヘッドを駆動しているため、正確な 位置決定を目的としたサーボ面を一面持っているものもあります。 この場合「HDD のジオメトリー」としてのデータ面 (ヘッド) の数は 奇数になります。一方、サーボ情報をデータ面に埋め込んで高密度化を 図ったドライブの場合にはヘッドの数が偶数になります。

1.4 セクター

ディスク上の各トラックを分割する単位であり、ディスクアクセスの 基本的な単位でもあります。 HDD の場合、通常は 1 セクターあたり 512bytes です。 (640MB の MO では 1 セクターあたり 2048bytes となります) すべてのトラックについてセクター数が同じ場合 (古い IDE HDD では そうなっていたようです)、ディスク上の各セクターはそれぞれ扇型の ような形となります。 「HDD のジオメトリー」として使用される「セクター数」は、 「トラック当りのセクター数」のことであり、これが (古い IDE HDD の 場合のように) ドライブ全体で共通であることを前提としています。

JF の large-disk-mini-HOWTO によれば SCSI ディスクの場合、内周の トラックと外周のトラックでセクター数が異なるため、ドライブ全体に 共通する「トラック当りのセクター数」というものは存在しません。 (セクター数の共通なトラックをまとめて "ノッチ" と呼びます)

目で見てわかる例として、3.5インチの 128MB MO と 230MB 以上の MO が あります。 MO はセクタの境界が目で見えます。注意深くシャッターを開けて見てみると、 128MB MO は扇型に溝がありノッチは見られませんが、230MB 以上の MO は 外側にいく程トラック当たりのセクタ数は多くなり、ノッチが見られます。 230MB以上のMOはこうすることで大容量化を計っているのです。 # なお、シースルーなMOならシャッターを開けなくてもわかります。

したがって「HDD のジオメトリー」の単位として使用される 「トラック当りのセクター数」には、すくなくとも SCSI ディスクの 場合、物理的な意味との対応は一般的に存在せず、単にマザーボード の BIOS がもつ仕様に合わせるためだけに使用されています。

また IDE ディスクでもかなり以前 (504MB の壁が話題になっていた頃 ?) から、 ディスクの内周と外周でセクター数が異なることは珍しくないようです。 (ディスク自体の構造は IDE でも SCSI でもまったく同じだったりする場合も あることをある人から指摘して頂きました。)


2. ディスクアクセス

さて HDD へのアクセスでは、セクター単位での読み書きが基本になります。 複数のディスク面から構成される一般的なドライブでは、どの面にある、 どのトラックの、何番目のセクターかを指定することが必要です。

2.1 3 次元 (3D) アドレス / CHS (シリンダー、ヘッド、セクター)

トラック当りのセクター数がすべてのトラックについて共通な HDD の 場合には、どのトラックかを指定するシリンダー番号、どのディスク面かを 指定するヘッド番号、そして何番目のセクターかを指定するセクター番号の 3 つを組み合わせて 3 次元 (3D) アドレスとしてセクター位置を指定すると いう方法が自然でした。

これは標準 IDE インターフェイスが使用する シリンダー番号:16bit, ヘッド番号:4bit, セクター番号:8bit の 計 28bit によってセクター位置を指定する方法に結びついています。 この 28bit により指定された各セクターが 512byte のサイズだとすれば、 アクセス可能なディスク容量は 512=2^9 より 28+9=37bit -> 2^37=128GB と なります。

ただし、もともとの BIOS の仕様では シリンダー番号指定に 10bit、ヘッド番号指定に 4bit、セクター番号指定に 1〜63 を使うようになっており、IDE の仕様とビット数の割り当てが異なっています。 このために両方で共通に使えるビット数はシリンダー、ヘッド、セクターに 対してそれぞれ 10bit, 4bit, 6bit の合計 20bit (しかもセクター番号は 6bit = 64 ではなく、ひとつ少ない 63 までしか使えない) となり、 アクセス可能なディスク容量は (2^14)*63*512/(1024*1024)=504MB と なってしまいます。これが (もうかなり前のことになってしまいますが) 有名な「504MB の壁」です。

2.2 ジオメトリ変換: ("LARGE")

この「壁」を回避するために、BIOS のメニューで "LARGE" と 表示されるジオメトリ変換方法と「LBA」という方法が利用されています。

「"LARGE"」とは、ディスク (IDE コントローラ) とのやり取りでは E-IDE の仕様に従って 16bit および 4bit で表現されるシリンダー番号、 ヘッド番号を使い、一方 INT13h を経由した OS とのやり取りでは もともとの BIOS 仕様に従った 10bit および 8bit で表現される シリンダー番号、ヘッド番号を使う、という方法です (セクター番号はBIOS 仕様に合わせて 1〜63 を共通に使います)。

具体的にはディスクの持つジオメトリー情報をもとに、シリンダ数を 2 で 割ってヘッド数に 2 をかける手順を繰り返し、シリンダ数が 1023 以下に なるか、あるいはヘッド数が 128 以上 になるまで続けるか、あるいは ヘッド数を 255 として「シリンダ数×ヘッド数」で求めた全セクター数を この 255 で割ってシリンダ数を求めます。 そしてこの手順で求めたシリンダ数、ヘッド数によるジオメトリ (L-CHS) を INT13h を経由した OS とのやり取りで使います。この方法によれば、 アクセス可能なディスク容量は 1023*255*63*512/1024/1024/1024=7.8GB と なります。 これがここしばらく話題になることの多かった「7.8GB (or 8GB) の壁」です。

2.3 ジオメトリ変換: LBA (Logical Block Addressing)

(注: 以前 LBA を "Linear Block Addressing" と 書いていたのですが、それは誤用だという指摘を受けました。 自分でも調べてみましたが、どうも今まで誤解していたようなので 訂正しておきます。情報提供、ありがとうございました。)

一方、セクター数がトラックによって異なる HDD の場合には、 3D アドレス を使用するより、むしろすべてのセクターに対して通し番号を付け、セクター 位置を一次元の (線形 = リニアな) 番号によって管理したほうが、効率上も わかり易さでもより良いと考えられます。 この「すべてのセクターに通し番号を付け、その番号によってセクター位置を 指定する」方法は "LBA" と呼ばれており、 すべての SCSI ディスクコントローラ、および 504MB 以上の大容量ディスクに 対応した IDE コントローラの多くはこの方法によってディスクにアクセスする ことができます。このセクター番号はパーティションテーブル内では 32bit に よって表現され、セクターサイズ 512bytes を前提とすればアクセス可能な ディスク容量は 32+9=41bit -> 2^41=2TB (テラバイト) となります。

ただし、OS やブートローダでは依然として従来の BIOS 仕様に従った 10bit および 8bit で表現されるシリンダー番号、ヘッド番号を使う、 という方法でアクセスするものが多いため、LBA によるリニアアドレスは ディスクコントローラとのやり取りでのみ利用され、INT13h を経由した OS とのやり取りではつい最近まで上記の "LARGE" で説明した 手順によって求めた CHS ジオメトリーを使います。 従ってアクセス可能なディスク容量は先程と同じく 7.8GB となります。

2.4 BIOS Extended (INT13h AH=4xh)

最近では IBM と MS により、INT13h AH=42h (Extended READ) や INT13h AH=43h (Extended WRITE) などの規格が提唱され、OS が INT13h BIOS コールを経由して直接「リニアアドレス」を利用できるように なってきています。

Linux カーネルのように起動後は BIOS を経由せず、直接ディスク コントローラにアクセスする OS では、以前から「カーネルが起動して しまえば」7.8GB の壁を気にすることなくディスクを利用できましたが、 新らしい BIOS call を使えば BIOS 経由でディスクにアクセスする OS であっても「7.8GB の壁」を超えてディスクを利用することができる ようになったわけです。

ただし、この BIOS call を実際に使っているソフトウェアはまだ数が少なく、 またドライブのほうで対応していない場合もあるようです。特に起動に使う ブートローダでこれに対応しているのは Free なものでは GRUB か extipl (extipl では sample としてこのためのコードが含まれています) くらいしか 私は知りません。Linux の起動用に使われることの多い LILO は version 21 以前は対応していません。LILO Version 22 では対応するためのコードが 入ったようです。("edd" option)

また、既存のパーティションを縮小するために利用されている FIPS は まだ v2.0 でも LBA BIOS コールには対応していないようです。 このため、HDD 上の 8GB を越える領域に対して現状の FIPS を使うと データを破壊する結果を招くと予想されます。

2.5 不具合のある BIOS

「E-IDE 対応」なはずのマザーボードには、時期によって対応可能な シリンダー数の上限が異なるものがあるようです。本来なら IDE の 仕様上限である 65536 シリンダーまで対応しているべきと思うのですが、 以前聞いた話ではディスクコントローラの問い合わせに対して ドライブ側が答えるシリンダー数が 4096 以上になると暴走するという 欠陥品的な代物の BIOS もあり、そのような場合の対策として BIOS からの 問合せに対してドライブが答えるシリンダー数を実際より少なく見せかける 設定のためのジャンパーが用意されている HDD もあるようです。

ところが Linux を使う場合には、このような不自然なジャンパー設定が かえって邪魔になって、せっかく使えるはずの LBA アクセスが使えなく なる場合もあるので要注意です。 一方ごく最近にはシリンダー数が 16bit (65535) を超えるような巨大な ディスクもあるようで、こういう場合にはカーネルにパッチを当てないと うまく扱えないという話もあります。 「BIOS Extended Read/Write」によるアクセスが普及して、CHS アドレスを 使ってアクセスしなくてもすむようになれば、こういう問題も解消される だろうと思われます。

2.6 BIOS で変換できない場合

もっと以前の「E-IDE 対応」ですらない BIOS を持つマザーボードでは、 ドライブの称するシリンダー数を 1024 で割った余りのシリンダー数しか 認識しないという例が多かったようです。 このため、シリンダー数 1100 程度のドライブだと BIOS の認識する容量が 数10MB 程度しか無くて困ってしまうという話題がけっこうありました。

で、そういう場合の対策としては手動で BIOS に HDD のシリンダー数を 1023 だとして 設定してしまって、とりあえず 504MB までは正常に BIOS から認識できるようにしておき、 はみ出す部分は Linux の (起動用には使えないので) データ領域として使うということが わりと一般的だったと思います。


3. パーティションについて

ハードディスクを使う場合、いくつかの理由から複数の領域に分割して利用することが 多くあります。この分割した領域を「パーティション」と呼びます。

(MO の場合にはパーティションに分割せずディスク全体をまるごとデータ領域として 使う場合もあります)

Linux システムでは 通常 "/" (ルート) ファイルシステム用のパーティションと スワップ用のパーティションのすくなくとも 2 つのパーティションを 使用します。 また "/home" ファイルシステムとして ユーザーのデータ領域を別のパーティションに分離することは、 バックアップやシステム情報の保存などに有効となります。

LDP/JF の Partitin-HOWTO の「2. ともあれパーティションとは?」や Disk-HOWTO などにパーティション分割の方法についての説明などがあります。

ところでパーティションには、 「基本 (primary)」、「拡張 (extended)」、「論理 (logical)」の区別があります。 ここでは、そのそれぞれの違いについて説明してみます。

3.1 基本領域 (primary partition)

「基本領域」というのは最初に定義された形式です。 この「基本領域」を定義する「パーティションテーブル」は ハードディスクの先頭 512 byte (最初のセクタ) の最後のほう 64bytes (最後に 0xAA55 の 2bytes がくるので、447バイト目から - 510バイト目まで) に収まるように定義されていて、かつ1つの「基本領域」を定義するために 16バイトが必要なため、「基本領域」はディスク全体で最大 4 個までしか 作成できません。

この 16bytes の中身 (ひとつの「基本領域」を定義する構造体) は 以下のようになっています。 (この部分は LDP/JF の large-disk-mini-HOWTO より引用)

   struct partition {
           char active;    /* 0x80: bootable, 0: not bootable */
           char begin[3];  /* CHS for first sector */
           char type;
           char end[3];    /* CHS for last sector */
           int start;      /* 32 bit sector number (counting from 0) */
           int length;     /* 32 bit number of sectors */
   };

ここで、 CHS は Cylinder/Head/Sector の略です。 また active は起動可能な領域であるかどうかを示すフラッグで、 type はそのパーティションの種類を示す ID (Linux の Ext2fs なら 0x83) です。begin[3] と end[3] は CHS アドレスによるパーティションの開始位置と 終了位置、また start と length は LBA アクセスのためのセクター番号による パーティションの開始位置とサイズです。 (/余談)

PC が生まれた頃はたぶんこれで問題無かったのでしょうけれど、 だんだんとハードディスクの容量が増えてくると、 もっとたくさんのパーティションを使いたくなります。 「拡張」と「論理」はこの要望に応えるために、 最初の形式を拡張したものです。

3.2 拡張領域 (extended partition)

「拡張」領域とはその中に「論理」領域を収めた基本領域です。 しごくあたりまえの説明ですが、単にそれだけです。 「拡張」領域の場所や大きさ、パーティション ID などは「基本」と同じく ハードディスクの先頭 512bytes (これをマスターブートレコード、MBR と呼ぶ) 内の パーティションテーブルに記録されます。

3.3 論理領域 (logical partition)

「論理」領域は「基本」や「拡張」と異なり、そのサイズや位置などの 情報は MBR に記録されません。では、どこに記録されているのか ?

(余談) 実はこれ、私は最近ようやく知って面白いと思ったのですが、 以前から AT 互換機に詳しい方には当然のことなのかもしれません。 (/余談)

実は、「論理」領域は「親亀の上に子亀、そのまた上に孫亀」といった感じの 連鎖構造になっています。

図で書くと、こんな感じ (等幅フォントで見てください _o_)

  1. 「拡張」領域内にひとつの「論理」領域

    大元の「拡張領域」の中に「先頭トラック」に相当するサイズのスペース (その中に「準」パーティションテーブルがある) と、 それに続いて論理領域が含まれています。

     |拡張領域全体
     |----------------------------------------------------
     |先頭トラック|論理領域
    

  2. 「拡張」領域内にふたつの「論理」領域

    大元の「拡張領域」の中に「先頭トラック」に相当するサイズのスペース (その中に「準」パーティションテーブルがある) と、 それに続いて最初の論理領域、そしてさらに次の「準」拡張領域が 含まれています。

    次の「準」拡張領域の内部は上記の 「拡張領域内にひとつの論理領域」と同じです。

     |拡張領域全体
     |----------------------------------------------------
     |先頭トラック|論理領域|「準」拡張領域
    
    
                        |「準」拡張領域
                        |--------------------------------
                        |先頭トラック|2 番目の論理領域
    

  3. 「拡張」領域内に 3 つの「論理」領域

    大元の「拡張領域」の中に「先頭トラック」に相当するサイズの スペース (その中に「準」パーティションテーブルがある) と、 それに続いて最初の論理領域、そしてさらに次の「準」拡張領域が 含まれています。これは上記の「拡張領域内にふたつの論理領域」 と同じです。

    次の「準」拡張領域の内部も「拡張領域内にふたつの論理領域」 と同じです。

    3 番目の「準」拡張領域の内部は上記の 「拡張領域内にひとつの論理領域」と同じです。

     |拡張領域全体
     |-----------------------------------------
     |先頭トラック|論理領域|「準」拡張領域
    
    
                |「準」拡張領域
                |------------------------------------------------------
                |先頭トラック|2 番目の論理領域|2 番目の「準」拡張領域
    
                           |2 番目の「準」拡張領域
                           |------------------------------------
                           |先頭トラック|3 番目の論理領域
    

「拡張」領域の先頭セクター (512 bytes) には、 その領域内に存在する「論理」領域と、 その次の「準」拡張領域の位置とサイズを記録した 「準」パーティションテーブル (512bytes のうちの 447 - 510 bytes, 計 64bytes の領域) が 存在します。

「準」拡張領域という名前は、この文書で便宜的に付けた名前です。 この領域の構造は大元の拡張領域とまったく同じで、ただその全体が 別の (「準」) 拡張領域に含まれるという点だけが違います。

「準」パーティションテーブルの形式は MBR にあるディスク全体の パーティションテーブルとほぼ同じ (ただし、セクターアドレスの計算方法にちょっと注意が必要) です。


4. おわりに

4.1 お願い

ここまで、とりあえず書けた部分だけでまとめてみましたが、 まだまだ不足している情報があるはずです。 「これも追加して欲しい」という意見をお持ちの方は 是非教えて下さい。よろしくお願いします。

4.2 謝辞

この文書は LDP/JF の large-disk-mini-HOWTO やその他の参考文献から 得られた情報をまとめたものです。Linux ユーザーの役に立つ文書を 数多く集積し、世界に発信している LDP と JF のみなさんに感謝します。 また、この「ハードディスクドライブの基礎知識」について、以下の方々 から有益なフィードバックを頂きました。ここに感謝の表します。

1999 10/06 修正: セクターおよび ディスクアクセスの文章を おくじさんからの指摘を参考に修正しました。

1999 12/5 追加: セクターにある MO の例は 飯塚さんからの情報提供によります。

4.3 この文書の配布について

 copyrighted (c) 1999 Taketoshi Sano

この文書は GNU パブリックライセンス (GPL) バージョン 2 かそれ以降 の条件、あるいは標準的な Linux ドキュメントプロジェクト (LDP) の条件に 基づいた配布ならば自由にしていただいてかまいません。これらのライセンス はこのドキュメントが入手できるようなサイトから入手できます。LDP の条件は (翻訳をのぞく) いかなる修正も許可していません。修正されたバージョンは GPL の基でのみ配布されるものとすることが可能です。


sgml21html conversion date: Sat May 20 22:37:06 JST 2000

[