システム奮闘記:その54

IDEハードディスクの入出力(I/O)の設定



Tweet

(2006年11月30日に掲載)
はじめに

  (E)IDEのハードディスクの入出力(ディスクI/O)
  hdparmコマンドを使えば、(E)IDEのハードディスクへの読み込みや
書き込みの速度を上げる事ができる。
  大量のデータのやりとりの場合に効果を発揮する。

  今回は、hdparmのコマンドの話を書く事にしました。
  

hdparmコマンドの概略

2006年1月、会社にある私の本棚を見る。 過去に買ったが「積ん読」になっている雑誌を見るためだった。 その中の一冊に「Linux WORLD 2001年11号」を取り出した。 特集「チューンアップ」の文字があった。 恐らく、私は書店でこの雑誌を見た時、「チューンアップ」の文字を見て 「勉強せねば」と思って買ったと思う。 しかし、内容が理解できずに、本棚に保管される事になった (^^;; それから4年以上経って、ようやく読む気が起こるレベルになった。 その中に、hdparmコマンドがあった。 (E)IDEハードディスクのI/Oに関する値を変更するためのコマンドだ。 早速、会社のサーバーのディスクI/Oの状態を見てみた。 すると以下の結果だった。
hdparmコマンドで、ディスクI/Oの状態を見てみる
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    = 16 (on)
 I/O support  =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
 keepsettings =  0 (off)
 nowerr       =  0 (off)
 readonly     =  0 (off)
 readahead    = 256 (on)
 geometry     = 65535/16/63, sectors = 78165360, start = 0
 busstate     =  1 (on)
[root@server]# 

  このままではディスクI/Oは遅いという。
  DMAが無効になっている上、I/Oのモードが16ビットになっている。

  本では、DMAを有効にする方法と、I/Oのモードを32ビットにする方法が
書いてあったので、本の丸写しで以下の事を行う。

hdparmコマンドで、DMAを有効にする
root@server]# /sbin/hdparm -d1 /dev/hda

/dev/hda:
 setting using_dma to 1 (on)
 using_dma    =  1 (on)
[root@server]# 


hdparmコマンドで、I/Oモードを32ビットに変更する
[root@server]# /sbin/hdparm -c1 /dev/hda

/dev/hda:
 setting 32-bit I/O support flag to 1
 I/O support  =  1 (32-bit)
[root@server]# 

  そして、hdparmコマンドで、ディスクI/Oの状態を見てみる。

hdparmコマンドで、ディスクI/Oの状態を見てみる
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    = 16 (on)
 I/O support  =  1 (32-bit)
 unmaskirq    =  0 (off)
 using_dma    =  1 (on)
 keepsettings =  0 (off)
 nowerr       =  0 (off)
 readonly     =  0 (off)
 readahead    = 256 (on)
 geometry     = 65535/16/63, sectors = 78165360, start = 0
 busstate     =  1 (on)
[root@server]# 
赤い部分は、I/Oモードの部分。32ビットになっている。
青い部分は、DMAの有無を見る。有効になっている。

  そこで、tar.gzファイルの展開などを行ってみたが、
感覚的に、展開速度が速くなっている気はしなかった。

  「まぁ、人間の目にはわからんレベルの話だろう」と思い込んだ私は
「そんなにシビアに速度を求めるシステムは使う事はない」と考え、
この時点は、追求する事はしなかった。


hdparmコマンドを勉強するキッカケ

だが、2006年3月、そのコマンドが活躍する時がやってきた。 ある日の事、カーネルのバージョンアップを行っていた。 ソースコンパイルで行う私なので、コンパイル後は、ブートローダーに 更新情報を教える必要がある。 私は、ブートローダーにLILOを使っている。 だが、Sambaサーバーでカーネルのバージョンアップの作業中、 LILOが機嫌を損ねた。そして・・・ LILOが死んでもうた・・・ (--;; ブートしても立ち上がらない。えらい事だ。 以前の私なら慌てふためく所なのだが、この時は、慌てる事なく、 「フロッピーでシステムの起動ディスクを作成すれば復旧できる」と思った。 そこで、起動ディスクを作成する。 そして、フロッピーディスクから起動させてみたが・・・ アカン、立ちあがらへん (--;; 本当に、えらい事だ・・・。 社内の重要データを入れているだけに、復活しなければ、私のクビが飛ぶ。 いや、クビが飛ぶくらいで済むなら、まだマシだ。 だが、慌てなかった。 一応、毎晩、データをテープでバックアップをとっているが、 もし、テープに不具合があり、バックアップがとれていない場合も考えられる。 もし、テープの不具合のために、2、3日前のデータしか戻せなかったら 仕方がない事なのだが、それは最終手段であって、HDDにあるデータを 生かしながら、普及作業を行う事が最優先だ。 さて、復旧作業を行う事にした。 Sambaサーバーのディスクパーティションは、システム部分とデータ部分を 分けている。 そのまま、システム部分だけをシステムの入れ換えを行い、 データ部分を触らなければ復活はできる。 だが、万が一、何かのトラブルで、データ部分まで壊れてしまったら 大事なデータはオシャカになる。 作業は慎重を要する。 さて、データ部分に入っているデータの吸い出しからだ。 でも、どうやってHDDからデータを救出するのか。 フロッピーで作成した起動ディスクが使えない。困った。どうしよう・・・。 だが、ふと気がついた。 KNOPPIXがある! 今まで、KNOPPIXは使った事がなかった。 社内のパソコンや、自宅のパソコンでは性能不足もあり、 一度、試しで入れてみたが、重い、遅いという事で、使わなかった。 だが、こんな非常事態になって、凄くありがたい存在だと思った。 初めて使うKNOPPIX。色々、触ってみると、ネットワークの設定もできるのを知る。 HDDにマウントして、救出したいデータがあるかを確認する。 無事、生きていた!! さて、これをいくつかの tar.gz のファイルにして、他のマシンに移すのだが、 データの量が巨大だ。時間がかかる。 この時、ふと思った。 hdparmコマンドを使えば、転送が速くなるかも ディスクI/Oの性能を上げれば、tar.gzへまとめる処理が早くなると思った。 その読みは当たった。定量的に測ってはいないが、感覚的に、処理が 速くなっていると感じた。 そして、ftpで他のマシンへデータ転送を行う際も、相手先のマシンの ディスクI/Oも、hdparmコマンドで高速化を行った。 データ転送が終わった。無事、データを救出できたので、これで一安心だ。 そして、Linuxをインストールしなおす。 もちろん、データの入っていた場所のフォーマットは行わず。 作業は円滑に進んだ。他のマシンへ避難させていたデータを戻す事なく、 Sambaが復旧したのだった。 なんとか事なき終えた。 今、思えば、冷静に対処できたと我ながら感心する。 まぁ、今まで何回か修羅場をくぐり抜けてきているだけに、 この程度のトラブルでは、復旧作業中に悲壮感はなかった。
さて、hdparmコマンドだが これはネタにできる! と思った私。 しかし、しばらくお蔵入りになった。何せ・・・ 別のネタの処理に追われる (--;; 連載初期の頃は、ネタがないので、のんびり書いていたのだが、今は違う。 ネタがネタを呼ぶ状態で、全く処理が追いつかない・・・。 パーマンのコピーロボットが欲しくなる心境だ。 コピーロボットに会社へ行かせて働いてもらい、私は執筆作業。 ゴーストライターが欲しくなると思う事もある。
ゴーストライターが欲しいよ〜
10人の話を同時に聞けるマルチタスクの聖徳太子と
キン肉マンに登場する手が何本もある阿修羅マンが合体した
コピーロボがあれば、執筆作業も格段に早くなると思う。

ただ問題は、私の文体を真似できる人でないとダメなのだ。

システム奮闘記だが、友人達には公開したとは宣伝しなかったが、
彼らは「Linux関係の事で検索して調べたら、お前のページが出てきたで。
あんな文章を書くのは、お前しかおらへん」と言う。

つまり、誰も真似できない文章を書くため、とても、なりすましで
原稿を書いてくれる人が募集できないのだ。


hdparmコマンド

2006年9月になって、詳しく hdparmコマンドの事を調べる事にした。 まずは「-a」オプションから。 これはハードディスクのデータの読み込みの際、先読みするセクタの数の 指定を行うオプションなのだ。 Linuxの場合、初期状態では、8セクタを先読みする。 1セクタは512バイトなので、8セクタは4Kバイトになる。 セクタって何やったっけ? 「システム奮闘記:その31」(Linux、Windowsのファイルシステム入門)で ファイルシステムの事を取り上げた。  だが、それ以降、ファイルシステムの勉強をしてないため、すっかり忘れている。 なので復習を行う。
ハードディスクの円盤構造
ハードディスク(HDD)の円盤構造
ハードディスクは円盤になっている。円周上の区域をトラックと呼び
トラックを、いくつか分割した最小単位をセクタという。

データ転送の場合、最小単位のセクタごとに転送されるため
それより小さい単位での転送は不可能だ。

  大きなファイルを読む場合、同じトラック上に連続してデータが
書き込まれている場合が多い。
  なので、先読みしておけば、それだけ読み込みが速いという話だ。

  
  実際に、読み込み速度を測ってみる事にした。

  測定の時のハードディスクの条件を次のようにした。

ハードディスクの設定条件
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    = 16 (on)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
 keepsettings =  0 (off)
 readonly     =  0 (off)
 readahead    =  8 (on)
 geometry     = 9964/255/63, sectors = 160086528, start = 0

  DMAを無効にして、I/Oを16ビットにしてみた。
  そして、先読みを8セクタと32セクタで比較してみた。

先読みが8セクタの場合
[root@setver]# hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 22.82 seconds =  2.80 MB/sec
先読みが32セクタの場合
[root@server]# hdparm -a 32 /dev/hda
[root@server]# hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 22.82 seconds =  2.80 MB/sec

  全然、変わらへん (^^;;

  何が悪いのかなぁと思いつつ、ハードディスクの条件を変えてみる事にした。
  そこでDMAを有効にしてみた。

ハードディスクの設定条件
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    = 16 (on)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  1 (on)
 keepsettings =  0 (off)
 readonly     =  0 (off)
 readahead    =  8 (on)
 geometry     = 9964/255/63, sectors = 160086528, start = 0

  DMAを有効にして、I/Oを16ビットという条件だ。
  そして、先読みを8セクタと32セクタで比較してみた。

先読みが8セクタの場合
[root@setver]# hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec
先読みが32セクタの場合
[root@server]# hdparm -a 32 /dev/hda
[root@server]# hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec

  これでも、全然、変わらへん (^^;;


  次に、DMAを無効、I/Oを32ビットにして比較してみる事にした。

ハードディスクの設定条件
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    = 16 (on)
 IO_support   =  1 (32-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
 keepsettings =  0 (off)
 readonly     =  0 (off)
 readahead    =  8 (on)
 geometry     = 9964/255/63, sectors = 160086528, start = 0

  DMAを有効にして、I/Oを16ビットという条件だ。
  そして、先読みを8セクタと32セクタで比較してみた。

先読みが8セクタの場合
[root@setver]# hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 13.83 seconds =  4.63 MB/sec
先読みが32セクタの場合
[root@server]# hdparm -a 32 /dev/hda
[root@server]# hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 13.83 seconds =  4.63 MB/sec

  これでも、全然、変わらへん (^^;;

  うーん、この実験だけだと先読みの効果が見えないようだ。


  こういう時、話を書くのが大変だ。
  効果が見えた場合だと、その次へ話の展開を持っていきやすいのだが、
この場合だとなぁ・・・。

  まぁ、良いや  (^^)  ← ええわけねぇーだろ!


  ところで、先読みのセクタ数が多いのが長所のように書きましたが、
そうとは限らない場合もあります。
  ランダムアクセスの場合、無意味だからだ。

  先読みが発揮されるのは、同じトラック上に連続したデータが
並んでいる場合だ。図にすると以下の状態の時だ。

先読みが発揮できる場合
ハードディスクの上のデータの先読みの仕組み
上図のように、同じトラック上に連続してデータが並んでいる場合
先読みしてキャッシュに保管すれば、次は、わざわざ読みに行かなくても
キャッシュのデータを使えば済むため、I/Oが速くなる。

  先読みが役に立たない場合は、以下の場合だ。

先読みが発揮しない場合
別々のトラック上にデータがある場合
データが不連続で、しかも別々のトラックに散らばっている時だ。
これだと、いくら先読みして、データをキャッシュに入れても
使われる事がないため、無駄になってしまう。

  ランダムアクセスの場合は、先読みのセクタの値が小さい事が
推奨されているようだ。

  どうやら、先読みセクタの値の、最適値は、場合によりけりになるため
「これが最適」と断言できる値はなさそうだ。


  セクタの先読みだが、Windows98にも同じような機能がある。

Windows98
Windows98の先読み最適化の設定
今更ながらWindows98の勉強です。
Windows98もハードウェアの知識が必要だなぁと感じました (^^;;


hdparmの「-t」と「-T」オプション

次に「-t」と「T」のオプションをみてみる。 「-t」のオプションだが、ハードディスクの読み込みの性能を 見るための物だ。 先ほど、「-a」オプションを使った際、読み込み速度を測定するのに 使いました。
「-t」オプション
[root@setver]# /sbin/hdparm -t /dev/hda

/dev/hda:
 Timing buffered disk reads:  64 MB in  5.10 seconds = 12.55 MB/sec

  「-T」オプションですが、キャッシュの読み込み速度を測定するものだ。

「-t」オプション
[root@setver]# /sbin/hdparm -T /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec

  さて、「-t」と「-T」を一緒にした「-tT」にする事ができる。
  これは、ハードディスクからの読み込み速度を測定する際に、
キャッシュ部分の補正を行ってくれる役目がある。
  より正確性を求めるには、「-tT」オプションにするのが良いみたいだ。


hdparmの「-d」オプション

次に「-d」オプションを見てみた。 これはDMAを有効にするかどうかのオプションで、「-d0」だと無効になり 「-d1」だと有効になる。 hdparm -d1 /dev/hda とすれば、DMAが有効になる。 ところで・・・ DMAって何? 表面的な知識としては、DMAが何かは知っている。 なにせ、2005年にOSの本などを読んだ時に出てきたのだ。 つまりこういう事だ。
DMAが無効の場合
DMAが無効の場合のCPUとハードディスクのやりとり
CPUがデータ転送の指示を全て行う。
そのため大量データのやりとりの場合、CPUの負担が大きくなる。

  CPUの負担を軽くするためにあるのがDMAという。

DMAを有効の場合
DMAが有効だとDMAがCPUの代行を行う
DMAがCPUに代わってデータ転送の指示を行う。
その間、CPUは別の仕事が行える上、忙しいCPUに代わって
DMAが指示を代行するため、I/Oそのものも速くなる。

  だが、突っ込んだ話になると・・・

  わかっていないのがバレバレ (^^;;

  というわけで、DMAの働きをキチンと勉強する事にした。


  そこで次の本を取り出した。
  「オペレーティングシステム」(清水謙多郎:岩波書店)

  ハードディスクからデータを読み込む場合だけでなく、
キーボードからデータが入力される場合など、データの入力をCPUに知らせるため
CPUに割り込みが入る。

  デバイス(装置)から、メモリへデータを転送する場合、
以下のような流れの動作を行う。

DMAが無効の場合
DMAが無効の場合のハードディスクの入出力を行う仕組み
各デバイス(装置)には、制御するためのデバイスコントローラーがある。
デバイスからデータ送信する事を、デバイスコントローラーに伝え、
デバイスコントローラーは、CPUにデータ送信を知らせる割り込み信号を送る。
CPUはデバイスコントローラーに、データ転送先などの指示を行う。
デバイスコントローラーは、デバイスにデータ転送の指示をして、
デバイスからメモリへデータが転送される。

  キーボード入力やマウスの操作なら情報量が少ない上、
CPUの高速な動きから考えてみると、どんなにタイプ打ちの名人でも
低速な入力になるため、CPUに負担がかからない。

  だが、ハードディスクにあるデータの場合などは大きな負担になる。
  なぜなら、データ転送の場合、一度に転送できる量は限られているため
細切れで送るのだが、この細切れの転送が起こる度に、CPUに割り込みが入る。
  図にすると以下の感じだ。

DMAが無効の場合
DMAが無効の場合、データ転送の仕組み
データが大きい場合、分割して送られるのだが、分割されたデータが
転送される度に、CPUに割り込みが入り、指示を行うため
CPUの負担が大きくなる。

  CPUの負担が重たくなると、他の処理に支障が出てくる。
  これではCPUの性能も発揮できない。

  それだけではない。忙しいCPUがデータ転送までやっているため、
I/Oも遅くなるのだ。
  CPUの性能は発揮できない、他の処理に支障がでる、I/Oも遅くなるわで
悪い事だらけになるのだ。


  そこで、CPUの負担を軽くする方法として、DMAがある。
  DMA(Direct Memory Access)で、直接、メモリにアクセスする機能だ。

  このDMAがある場合だと、デバイスからメモリへデータを転送する場合
以下の流れになる。

DMAが有効の場合
DMAが有効の場合、CPUの代行を行う仕組みになる
各デバイス(装置)には、制御するためのデバイスコントローラーがある。
デバイスからデータ送信する事を、デバイスコントローラーに伝え、
デバイスコントローラーは、CPUにデータ送信を知らせる割り込み信号を送る。
CPUはDMAに処理代行のための指示をする。

DMAは、デバイスコントローラーに、データ転送先などの指示を行う。
デバイスコントローラーは、デバイスにデータ転送の指示をして、
デバイスからメモリへデータが転送される。

  もちろん、データ転送の場合、分割して転送されるのだが、
DMAがある場合だと、最初の1つ目のデータの場合だけ、
CPUに割り込み信号が入る物の、あとのデータに関してはDMAが代行してくれる。

DMAが有効の場合
DMAが有効の場合、CPUの代行を行い、CPUの負荷が軽くなる仕組み
CPUが割り込み信号を受けるのは最初の一度目だけで
あとはDMAが代行してくれるため、CPUの負担が軽くなる。

  実際に、CPUの負担が軽くなり、I/Oの速度に変化があるのか
実験を行ってみた。

  純粋のDMAの効果だけ見るため、以下の条件で実験を行う事にした。

実験条件
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    =  0 (off)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
 keepsettings =  0 (off)
 readonly     =  0 (off)
 readahead    =  8 (on)
 geometry     = 9964/255/63, sectors = 160086528, start = 0
マルチセクタの転送をしない。I/O転送を16ビットにした。

  その上で、DMAの有無だけで測定を行った。

I/Oの性能比較
DMA無効の場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.40 seconds =320.00 MB/sec
 Timing buffered disk reads:  64 MB in 24.12 seconds =  2.65 MB/sec
DMA有効の場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.13 seconds = 56.64 MB/sec

  飛躍的にI/Oの性能が上がっているのだ!

  単純に数値だけで見たら、21倍以上の差が出ているのだ。
  DMAが必要なのが、納得できる。

  もちろん、全てのハードディスクで21倍以上の差が出るわけではない。
  古いDMAだと、そんなに高速になるわけでもないようだ。


  ところで、DMAの有効・無効の設定はLinuxだけの話ではない。
  Windowsでもできる。そこでよく使っているWindows98でやってみる事にした。

Windows98でのDMAを有効にする方法
Windows98のシステムプロパティーの画面
ディスクドライブの「IDE DISK」を選択して、次に下の赤く囲んだ
プロパティーを選択します。

  すると以下の画面が出てきます。

Windows98でのDMAを有効にする方法
Windows98のシステムプロパティー画面でDMAを有効にする方法
DMAの有効・無効は赤く囲んだ部分の印で行います。

  Windows98は出た頃から使っていたのだが、DMAの有効・無効の話は
初めて知った。

  今更ながら・・・

 Windows98の勉強になった (^^)

  だが、Windows98の場合は、DMAの有効・無効だけであって、
転送モードについては細かい設定ができない。

  しかし、WindowsXPの場合は可能だ。

WindowsXPでのDMAを有効にする方法
WindowsXPのコンピューター管理画面
「プライマリーIDE チャンネル」の所で、プロパティを見てみる

WindowsXPでのDMAを有効にする方法
WindowsXPのDMAを有効にする画面
DMAの有効・無効は赤く囲んだ部分の印で行います。
「ウルトラ DMAモード」については、後述しています。


hdparmの「-c」オプション

次に、hdparmの「-c」オプションを見てみた。 これはデータのI/Oを16ビットにするか、32ビットにするかのオプションだ。 「-c0」だと16ビット、「-c1」だと32ビットだ。 hdparm -c1 /dev/hda とすれば、I/Oが32ビットになる。 最初、これを使った時、ある事に気づいた。 DMAが有効の場合、全くといって良いほど、変化がないのだ。
I/Oの性能 (DMAが無効の場合)
16ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.40 seconds =320.00 MB/sec
 Timing buffered disk reads:  64 MB in 24.09 seconds =  2.66 MB/sec
32ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 14.99 seconds =  4.27 MB/sec

  16ビットの時よりも、32ビットの方が1.6倍、転送速度が上がっている。

  だが、DMAを有効にして比較してみると

I/Oの性能 (DMAが有効の場合)
16ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec
32ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec

  全く同じ転送速度なのだ。
  だが、この時点では、DMAが無効の場合、転送速度が速くなっているから、
それで良いかと思った (^^;;


  そして、そんな事を気にせず「-c」オプションの事を調べる事にした。

  RedHat7.3、RedHat9.0、Plamo4.0では、初期値が16ビットになっている。
  他のディストリビュータは、どうなのか確かめていないため、わかりませんが
どうやら全て16ビットになっているようだ。

  ところでI/Oって何?

  この時、「I/Oのビットは、データバスの本数の事だ」と思った私は、
次の事を思い浮かべた。

データバスについて
データバスはCPUとメモリと入出力装置を結んでいる
CPU、メモリ、I/Oデバイス(ハードディスクやプリンタなどの入出力装置)は
バスというデータを転送する回線で結ばれています。

8086〜286マシンでは、データバスは16本でしたが、
386、486マシンは32本(ただし、386SXに関しては16本)
そして、Pentiumでは64本です。

電気信号は「0」、「1」で表現できるので、1本の線で1ビット表現ができる。
16本あれば16ビット、32本あれば32ビットの表現ができる。
そのため、16本だと16ビットのデータ(2バイト)のデータが、
32本だと32ビット(4バイト)のデータが転送できる。

  さて、hdparmでは、ディスク入出力(I/O)を
16ビットと32ビットの切り替えができる。
  切り替えができる理由だが、単純な発想をする私は以下のように考えた。

  初期値が16ビットなのは、互換性の事を考えた結果!
  Linuxの場合、386マシンでも動くようにするため、16ビットにしている!
  そして、486以降のマシンで快適に動くため、手動で32ビットにできる!

  つまり以下のように考えたのだ。

386SXでも動くように
386SXでも動くためなのか
386SXはデータバスが16本しかない。
そのため、386SXでも動くように、ディスク入出力(I/O)の
初期値を16ビットに設定しているものだと考えた。

  そして、他のマシンでは、快適に動かせるように、手動で32ビットに
変更できるようにしたと考えた。

486以降では
486以降ではバスが32本になる
486では、32本のデータバスがあるので、16本しか使わないのは
もったいない。なので、32本を使えるように
「-c」オプションで設定できるようにした。

  だが、この考えだと次の痛いツッコミを受ける。

  「Pentiumは64ビットだけど、なんで64ビットの設定がないの」

  だが、この時は「なんでやろ」と思ったが、あまり疑問に思わなかった。

  というわけで、簡単に説明できた思った。しかし、だいぶ後になり

  危うくデタラメ書く所だった!!

  がわかった (^^;;


  正しくは何だろうか。
  そこで、googleを使って調べて行く。
  だが、なかなか答えが書いているサイトが見つからない。

  諦めかけた時、SCSIのハードディスクのバス幅の数値が見つかった。
  現在でもSCSIのハードディスクは、データ幅が16ビットなのだ。
  古いSCSIの規格だと8ビットなのだが、10年以上も前の話だ。

  もしかして、SCSIのハードディスクのバス幅に対応するために、
ハードディスクのI/Oの値を16ビットにしているようだ。
  これだと「なるほど」と思える (^^)

  ところで、実際に、SCSIのハードディスクに対して以下のコマンドを打てば
エラーが出るのかどうかやってみたい。

  hdparm -c1 /dev/XXX

  だが、身近にSCSIのハードディスクを使っているLinux環境がない。
  なので、自分の目で確かめたくても、確かめられないのらー!  (^^;;


  めでたしめでたしと思ったが、ふと man hdparm の結果を見てみると

man hdparm の結果
DESCRIPTION
       hdparm  provides  a  command line interface to various hard disk ioctls supported by the
       stock Linux ATA/IDE device driver subsystem.  Some options may work correctly only  with
       the  latest  kernels.   For best results, compile hdparm with the include files from the
       latest kernel source code.

  hdparmは、あくまでもIDE(E-IED)のディスクのみのコマンドだった。

  危うく大恥をかく所だった (^^;;


  ちょっと話を脱線させて、IDEについて書きます。

  実は、この奮闘記を書く前は、IDEといえば、内蔵ハードディスクや
内蔵CD-ROMの規格と思っていました。
  間違えではないが、それ以上の知識はありませんでした (^^;;

  調べてみる事にした。

IDEって何?
良い機会なので、そもそもIDEとは何かを調べてみる事にした。

Compaq社とハードディスク・メーカーの米Western Digital社が
共同開発したハードディスク用の接続インターフェイスなのだ。
その後、仕様が拡張されて「Enhanced IDE」(E-IDE)になり、
今、パソコンなどのハードディスクは、EIDEが標準になっている。

ところで、内蔵ハードディスクなどをIDEだけでなく、
ATAという場合もあるが、これは、1988年に、ANSIによって、
IDEの規格が標準化さて、ATAという名称になった。
まぁ、IDEとATAは同じ物と考えても良いかもしれない。

  こんな事、全く知らなかったのらー!!


  閑話休題。

  うーん、一体、I/Oの初期値を16ビットにしている理由と、
Pentiumのデータバスが64ビットなのに、hdparmでは実装されていない理由が
いまいち見えて来ない

  サイコロを転がしても、振出に戻されてばかりだ。

  同じ時期、BIOS関係の本を読んでいた。
  「これならわかる BIOSの設定とアップデート」(前川 武弘:ディーアート)

  マザーボードの話が出ていた。

マザーボードの概略
マザーボードの概略
CPUからノースブリッジ(チップの一種)までデータバスがある。
ノースブリッジからサウスブリッジには、PCIバスと呼ばれる線がある。
補足
ノースブリッジとサウスブリッジの間は、PCIバスという線で
結ばれると書きましたが、後でわかった話、マザーボードの種類によって
PCIバスではなく、V-Linkバスだったり、HUB-Linkバスだったり、
MuTIOLだったりします (^^;;

  さて、上の配線で一度に送信可能なビット数は、以下のようになっている。

マザーボードの概略(バスの数など)
マザーボードの概略とバスの数
CPUからノースブリッジと呼ばれるチップまでPentiumだと64本の
データバスがある。
ノースブリッジからメモリも64本のデータバスが走っている。

ノースブリッジからサウスブリッジには、PCIバスと呼ばれる線があり、
ここは32ビットのデータを送る線がある。
最新のPCIバスだと64ビットになっている。

  PCIバスができる前は、ISAバス、VLバスといった低速なバスと、
IDEのハードディスクが結んでいたという。
  これらのバスは16ビットだという。なので、これらのバスにも対応するため
IDEのハードディスクのI/Oが16ビットになっているのではないかと推測する。


  さて、ところで、PCIバスが最新で64ビットなのを見て、
とんでもない誤解をした。

  サウスブリッジとIDEのケーブルを結ぶ線と
  PCIバスを混同したのだ!!

  なので、最新のマザーボードだと、IDEのハードディスクには一度に
64ビットのデータが送れると勘違いを起こしてしまった。


  そんな誤解したため、以下のような疑問を持った。

  I/Oで64ビットがないのはなんでやろ・・・

  考えてもわからない。こんな時、ふと思った。

  hdparmのソースを読めばわかるかも (^^)

  我ながら単純な発想だ。

  というわけで、早速、以下のサイトからhdparmのソースをダウンロードした。
  http://www.linuxfromscratch.org/blfs/view/stable/general/hdparm.html

hdparmのバージョン
2006/11/6 時点の最新版 Ver 6.9
RedHat9.0 Ver 5.2
RedHat7.3 Ver 4.6
Plamo 4.0 Ver 3.3

  普段、RedHat7.3を使っているが、もしかしたら、最新版を使えば、
I/Oが64ビットも実装されているのではないか。

  今、思えば、ハードウェアの事を全く理解していない行動なのだが、
この時は、そんな事を知らないため「前進あるのみ!」で突き進んだ。

  という事で、hdparm の ver6.9 をダウンロードした。
  そして、展開してソースを見てみた。
  早速、man の元になるファイルを見てみた。
  すると、I/Oは16ビットか、32ビットのどちらかだった。

hdparm.8 ファイルの中身
.I -c
Query/enable (E)IDE 32-bit I/O support.  A numeric parameter can be
used to enable/disable 32-bit I/O support:
Currently supported values include
どうやら64ビットはないようだ。

  どんな実装になっているのか興味があった。
  しかも、ソースコードが短いので

  私でも読めるのらー!!

  なので、I/Oの値に関する部分が意外と簡単に見つかった。

I/Oに関する部分 (hdparm.c)
if (set_io32bit) {
        if (get_io32bit)
                printf(" setting 32-bit IO_support flag to %ld\n", io32bit);
        if (ioctl(fd, HDIO_SET_32BIT, io32bit))
                perror(" HDIO_SET_32BIT failed");
}
赤い部分が設定変更を行う部分だ。
ここでコケたらエラーが出る仕組みになっている。

ioctl()関数は、デバイスを制御するシステムコールで、何でも屋に近い。
そのため使い方を網羅するのが大変なためか、このシステムコールに関して
詳しく書いている本がなかったりする。

  ソースを眺めて行くと、DMAの有効・無効も、ioctl()を使っている。
  ioctl()のシステムコールの使い方は、全く知らないだけに、
そんな役目があったと思うと勉強になる。


  ふとIDEの規格に関する本を見ていると、初歩的な事に気がつく。

  IDEのケーブル線って、40本やないか!

  後で気づいた話、実際には、IDEのケーブル線は39本だ。
  39本しかないのに、64ビット表現なんぞ不可能だ!
  最新の64ビットのPCIバスと混同していた事に気づいた。

  これで64ビットでない理由がわかった。

  IDEのケーブルだとデータ転送が最大32ビットだと思った。

  16ビットに設定できるのは、恐らく古いISAバスや、VLバスに
IDEのハードディスクを接続している場合を考慮しているためだと思うが
あくまでも推測の域を超えない。


  ところで、IDEのケーブル線は39本だ。

IDEのケーブル
IDEのケーブルとピンの数39本
IDEケーブルの接続部の拡大

  なぜ、32本ではなく、39本なのか。謎だ・・・
  そこで調べてみる事にした。以下の本を読んでみた。

  「チップセットの秘密」(安井健治郎:ディアート)

  ECC付きのメモリの話の部分だ。
  ECCとは「Error Check and Correct」でエラー検出・訂正の事だ。

  メモリにそんなのがあったとは知らなかった (^^;;

  ハードウェアについて、ある程度、知っているとばかり思っていたのだが
知らない事だらけである事が、どんどん露呈していく。


  ところで、32ビットを表現するには、32本の線で十分なのだ。
  なので、IDEケーブルが32本以外に、残り7本は何に使うのか疑問に思う。

  実は、この残り7本を次のように考えれば合点がいく。
  7本は「hamming code」(ハミングコード)と呼ばれるエラー検出・訂正用のビット。
  32ビットの場合、エラー検出・訂正用ビットに必要なビット数は「7」だという。

ハミングコード(Hamming Code)のビット数
送信データのビット数から、ハミングコードのビット数を求める式
2を底としたlogの式で表せる。
ちなみに、64ビットの場合は、誤り訂正ビットは8ビットになる。
ビット数が増えても、logの割合で増えるため、誤り訂正に使うビットは
そんなに大幅には増えない。

  32 + 7 = 39

  というわけだ。
  これを知って、なるほどと思った。

  だが、外れの可能性もある。
  何せ、IDEの39本のうち7本がエラー検出・訂正ビットと書いている文献や
サイトが見つけられなかったからだ。

  しかし、収穫があった。
  今まで、非ECCメモリとか、ECC付きメモリの意味がわからなかったのだが、
今回、初めて知ったのだ。これで良しとしよう。

  さすがに調べるのも疲れてきたので、常套手段である
「事務員なのでわかりません」で逃げようと思った。

  だが、その矢先だった。
  「事務員であっても逃げられない物」を発見してしまった。
  それは何かというと・・・

  IDEには誤り訂正ビットがない!

  なんと「32 + 7 = 39」と書いて、7ビットはハミングコードと書いたが
それが100%間違いである事が発覚した。

  あやうく大ウソ書く所だった (^^;;

  早めに逃げておけば良かった。
  これは調べだしたら泥沼にハマるだろうと思ったのだが、私の性格も働いて

  調べないと気が済まないのらー!!

  そこで調べる事にした。
  すると、IDEのピンの事で調べてみると以下のサイトを発見。
  http://pinouts.ws/ata-ide-pinout.html

  そこでわかった事は・・・

  IDEのケーブルだと16ビットしか転送できない!!

  IDEのピンと、それに対応した物が載っていた。

IDEのピンと、対応した役目
IDEの接続部分のピンの図
NSignalDescription
1/RESETReset
2GNDGround
3DD7Data 7
4DD8Data 8
5DD6Data 6
6DD9Data 9
7DD5Data 5
8DD10Data 10
9DD4Data 4
10DD11Data 11
11DD3Data 3
12DD12Data 12
13DD2Data 2
14DD13Data 13
15DD1Data 1
16DD14Data 14
17DD0Data 0
18DD15Data 15
19GNDGround
20KEYKey
21n/cNot connected
22GNDGround
23/IOWWrite Strobe
24GNDGround
25/IORRead Strobe
26GNDGround
27IO_CH_RDY
28ALEAddress Latch Enable
29n/cNot connected
30GNDGround
31IRQRInterrupt Request
32/IOCS16IO ChipSelect 16
33DA1Address 1
34n/cNot connected
35DA0Address 0
36DA2Address 2
37/IDE_CS0(1F0-1F7)
38/IDE_CS1(3F6-3F7)
39/ACTIVELed driver
40GNDGround

  上の表で「GND」となっているのは、アースの役目を果たす線だ。
  なぜ、アースがあるのかは、すぐ後に書いています。

  誤り訂正がない事がわかる。
  しかも、16ビットでしか転送できない事がわかる。

  一体、I/Oの設定で32ビットとは、どこの部分を指すのだろうか。
  もしかして、ハードウェアに関係なく、Linux内部でのI/Oの処理機構の設定に
関連する物なのだろうか。
  

  調べていくについて、ある文章を目にした。
  それは「IDEはパラレル転送」と書いていた物だった。

  パラレルってプリンタケーブルじゃないの?

  「なんで」と思いつつ調べて行くと、パラレルポートと混同していたのだ。
  今まで「パラレル=プリンタのケーブルと差し込み口の事」と思っていた。
  USB接続のプリンタが出る前は、パラレルポートを使っている。
  なので「古いプリンタ=パラレル」という思い込みがあった。

  だが、調べてみたら「パラレル」は Parallel で、「並行」という意味で
プリンタの意味は全くない。

  どんどんハードウェアの知識がないのが露呈されていく (^^;;

  さて、パラレル転送とはIDEのケーブルのように、信号を送る線が
何本も「並行」して走らせている事を意味している。

パラレル転送
パラレルの場合、39本の線が並行に並んでいる
IDEのケーブルの場合、40本並行して線が並んでいる。
(まぁ、実際には39本なのだが・・・)

そして、個々の線で別々の信号を送っている。
同時に何ビットもデータが送れるというわけだ。
並行している線が、それぞれ電気信号を流している

  さて、このパラレル転送だが問題点もあるという。
  信号線だが、電気信号を送れば、周囲に電磁波が発生する。

信号線から電磁波が出る
電気信号が流れる線では、電磁波が発生している
電気信号を送る際、電位が変化する事から周囲に電磁波が発生する。
これを数式化した物が、マックスウェルの方程式だ。
まぁ、大学では物理学科に所属していたので、ここまでは書けるが、
詳細については「忘れた」にしておきます (^^;;

  さて、この電磁波だが、次のような悪さを引き起こす事が
充分に考えられる。

電磁波による悪影響
それぞれで発生した電磁波が干渉する様子
個々の信号線から発生する電磁波が、他の信号線に対して
悪影響を起こす可能性が充分にある。
これがノイズの原因になったりする。

ノイズを減らす方法として、実は、39本の線のうち、いくつかが
GND(GROUND)になっている。つまりアースの役目を果たしている。
これにより、できるだけ電磁気の影響を排除しようとしている。

  電気信号にノイズがのるのは、他の線で流れた電気信号から発生した
電磁波の影響以外にも、他の電磁波などの影響もある。

  IDEの場合、誤り訂正がないのだ。
  そのため、ノイズにより信号がおかしくなっても信号の訂正どころか
誤り検出すらできないのだ。

  信頼性に問題が生じる事になる。

  今までそんな事、知らなかった (^^;;
  
  さて、SCSIのハードディスクには、転送されるデータの誤り訂正用の
ビットデータも用意されている。
  なので、信頼性を向上させるには、IDEよりもSCSIの方が良いと書いている。

  ここで以前からの謎が解けた。

  サーバー機種にSCSIを使っている理由がわかった!!

  以前からサーバー機種の広告などを見て、ハードディスクが
SCSIになっている事から「なんでやろ」と思っていた。

  SCSIの方がデータの読み書きでは信頼できるため、安全性を確保するため
SCSIを使っているのだ。これで納得できる (^^)

お詫びと訂正(2007/1/20)
IDEケーブルを伝送中のデータが電磁気の影響を受けて、
データの中身がおかしくなっても、現在は対策がとられています。
データ転送時に、CRCビットという誤り訂正符号も付けています。
これは、ATA3からサポートされています。調査不足で、すみません m(--)m

  さて、IDEとSCSIと比べるとデータ転送もSCSIの方が良い。

SCSIについて、私が誤解していた事
この奮闘記を書く前まで、SCSIは低速でIDEは高速と思い込んでいた。
「IDEは内蔵型だから速い」、「SCSIは外付けだから遅い」という
誤解をしていたのだった。

そのため、サーバー機種にSCSIのハードディスクを使っているので
「なんで遅い外付けのハードディスクを使うのやろ」と思っていた。

だが、IDEよりSCSIのハードディスクの方が高速だというのを知り
どんどん自分のボロが噴出していると感じると同時に、
初期のシステム奮闘記を書いている頃の自分の姿を感じる (^^;;

ボロが噴出している方が、自分らしくて良いかなぁと思ったりもする (^^)

  さて、一体、hdparmの設定のI/Oの16ビットと32ビットは何が違うのかが
見えなくなってきた。
  ヤケを起こして「えい、わかるかい!」と投げやりになってしまうそうだが、
冷静に、man hdparmを見てみた。

man hdparmの内容の抜粋
       -c     Query/enable  (E)IDE 32-bit I/O support.  A numeric
              parameter can be used to enable/disable 32-bit  I/O
              support:  Currently  supported  values include 0 to
              disable 32-bit I/O support, 1 to enable 32-bit data
              transfers,  and  3  to enable 32-bit data transfers
              with a  special  sync  sequence  required  by  many
              chipsets.  The value 3 works with nearly all 32-bit
              IDE chipsets, but incurs  slightly  more  overhead.
              Note  that "32-bit" refers to data transfers across
              a PCI or VLB bus to the interface  card  only; all
              (E)IDE  drives  still have only a 16-bit connection
              over the ribbon cable from the interface card.
青い部分は「32ビットのデータ転送は、PCIかVLBバスに接続したカードまで」で
赤い部分は「全ての(E)IDEドライブは、16ビットしか対応していない」
と書いている。

  図にすると以下のようになるという。

I/Oの設定が16ビットの場合
入出力(I/O)が16ビットの場合の図式
PICバスをデータが通る際も、16ビットのままで転送されるようだ。

  I/Oの設定が32ビットの場合は、下図のようになる。

I/Oの設定が32ビットの場合
入出力(I/O)が32ビットの場合のバスのデータ転送について
PICバスをデータが通る際も、32ビットで転送されるようだ。

  すなわち、IDEドライブを使っている場合は、32ビットにしても
IDEケーブル上では、16ビットでしかデータ転送ができない事から、
I/Oの設定は意味がない事なのかと思ってしまう。


  だが、疑問は残る。
  ここで、データの転送速度を測定した時を思い出す。

  DMAを無効にして、16ビットと32ビットの両方で測定した場合、
I/Oの性能が32ビットの方が上なのだ。

I/Oの性能 (DMA無効の場合)
16ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.40 seconds =320.00 MB/sec
 Timing buffered disk reads:  64 MB in 24.09 seconds =  2.66 MB/sec
32ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 14.99 seconds =  4.27 MB/sec

  確かに、16ビットの時より、32ビットの方が1.6倍、転送速度が上がっている。
  だが、DMAを有効オンにして比較してみると

I/Oの性能 (DMA有効の場合)
16ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec
32ビットの場合
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec

  16ビットと32ビットだと、I/O性能に、ほとんど違いがない。
  一体、なぜなのか。調べたくても・・・

  事務員なので、わかりませーん (^^)V

  ここまでくれば、工学部の世界だ。
  残念な事に、googleなどで検索したり、書店で本を探したが
見つける事ができなかった。

  ここで仮説を立てる事にした

  DMAが無効の場合、CPUに負担がかかる。
  CPUの負担を軽くし、データ転送を速くするには、CPUへの割り込み回数を
減らす事が考えられる。
  データは分割して送られる。16ビットの場合、一度に2バイトしか送れないが
32ビットの場合だと4バイト送れる。

  つまり以下のようになるのではないかと考える。

DMAが無効の場合を考えてみた
仮説:DMAが無効の場合のデータ転送の方式
16ビット転送と、32ビット転送を比較すると、CPUへの割り込み回数が倍違う。
32ビットの方が割り込みが半分になるため、CPUへの負担が軽くなる上
デバイスコントローラー(IDEコントローラー)への指示も半分になる。
そのため転送が速くなるのではないかと考えられる。

  では、逆にDMAを有効にした場合を考えてみる。

DMAが有効の場合を考えてみた
仮説:DMAが有効の場合のデータ転送の方式
16ビット転送と、32ビット転送を比較すると、CPUへの割り込み回数が倍違うが
どちらの場合であっても、CPUへの割り込みは最初の1度目だけだ。
CPUへの負担は変わらない。
そのため、I/Oの性能は変化しなくても、不思議ではない。

若干遅くなる理由は、見当もつかないが、I/Oの性能が変わらない場合だと
この説明が成り立つ。

  ハードウェアを解読したり、ソースを解読したわけでないため、
仮説の域を超えないのだが、これだと辻褄は合う。


  ここで調査終了と宣言しようと思った。
  だが、その後、この仮説も正しくない事がわかった。

  なぜ、正しくない事がわかったのかは、次の「-m」オプションで説明します。
  なので、ここで「-c」オプションの話は中断させていただきます。

SATAのハードディスク 「-m」オプションの話に進む前に、ちょっとした余談。 ところで、この部分を読んだ方で「最近のIDEのハードディスクはSATAやで」 とおっしゃる方がおられると思います。 実は、この調査をしている時、初めてSATAの存在を知りました (^^) SATA(Serial ATA)という規格で、これはシリアル転送なのでデータが 1ビット単位で、ディスクとマザーボードの間を通信している。 だが、身近な所でSATAのハードディスクがないため、 実験も何もできないのが残念・・・。

hdparmコマンドの「-m」オプション

さて、「-m」オプションについて説明します。 これは1度に複数のセクタを転送するためのオプションで、 「-m 4」とすれば、4セクタ同時に転送するという意味になる。 man hdparm で見てみる。
man hdparmの結果
-m     Get/set  sector count for multiple sector I/O on the drive.  A set-
       ting of 0 disables this feature.  Multiple  sector  mode  (aka  IDE
       Block  Mode),  is a feature of most modern IDE hard drives, permit-
       ting the transfer of multiple sectors  per  I/O  interrupt,  rather
       than  the  usual  one  sector  per interrupt.  When this feature is
       enabled, it typically reduces operating system  overhead  for  disk
       I/O  by  30-50%.   On many systems, it also provides increased data
       throughput of anywhere from 5% to 50%.  Some drives, however  (most
       notably  the  WD  Caviar  series), seem to run slower with multiple
       mode enabled.  Your mileage may vary.  Most drives support the min-
       imum  settings  of  2,  4, 8, or 16 (sectors).  Larger settings may
       also be possible, depending on the drive.  A setting of  16  or  32
       seems  optimal  on  many systems.  Western Digital recommends lower
       settings of 4 to 8 on many of their drives, due tiny  (32kB)  drive
       buffers and non-optimized buffering algorithms.  The -i flag can be
       used to find the maximum setting supported by  an  installed  drive
        (look for MaxMultSect in the output).  Some drives claim to support
       multiple mode, but lose data at some settings.  Under rare  circum-
       stances, such failures can result in massive filesystem corruption.
赤い部分を見ると、通常は1セクタを転送する度に割り込みが入るのだが、
このオプションを使えば、複数のセクタを転送してから割り込みが入るという。

青い部分を見ると、ディスクへの入出力の負担が30〜50%ほど減るため
データの入出力の速度が5〜50%ほど速くなると書いている。

  割り込み発生は、通常、1セクタ(512バイト)を転送するごとに起こっていたのを
複数のセクタを転送に変更するというのだ。


  この部分に着目すると、「-c」オプションで出てきた話で、
私が書いた仮説で、おかしい事に気づく。
  DMAをオフにして、割り込みを使ってデータ転送を行う際に、
16ビット(2バイト)を転送する度に割り込みが発生するか、
それとも32ビット(4バイト)の転送の度に割り込みを発生させるかの違いと
書いたが・・・

  完全に誤りだったのだ (^^;;

  そこで、分厚い「詳解LINUXカーネル」を取り出して
I/Oの事を調べてみた。

  すると、ハードディスクなどの大量データ転送を扱う装置は、
ブロック型デバイスという。

  ブロック型デバイスの場合、ブロック単位でデータを転送するため、
割り込みが入るのも、ブロック単位だという。

  つまり図にすると以下のような図式になる。

DMAが無効の場合
DMAが無効の場合のデータ転送の仕組み
ハードディスクからはブロック単位でデータが転送される。
そのため、DMA無効時に、ハードディスクからメモリへデータが転送時は
1ブロックごとにCPUに割り込みが入る。

もし、1ブロックのデータ量が、1セクタ(512バイト)だと、
4Kのデータを運ぶのに、8回の割り込みが入るが、
1ブロックのデータ量が、8セクタ(4Kバイト)だと、
4Kのデータを運ぶのに、1回の割り込みが済む。

  初期設定では、ハードディスクの場合、1ブロックは、1セクタのようだ。
  だが、1ブロックのサイズは変更可能なため、2セクタや、4セクタにできる。


  さて、実際に複数のセクタごとに転送すれば、速度が速くなるのか
実験をしてみる事にした。

実験の条件
[root@server]# /sbin/hdparm /dev/hda

/dev/hda:
 multcount    =  0 (off)
 IO_support   =  0 (default 16-bit)
 unmaskirq    =  0 (off)
 using_dma    =  0 (off)
 keepsettings =  0 (off)
 readonly     =  0 (off)
 readahead    =  8 (on)
 geometry     = 9964/255/63, sectors = 160086528, start = 0
I/Oは16ビット。DMAは無効にした。

  1セクタ転送と、16セクタの転送を比較してみた。

DMA無効、I/O 16ビット
1セクタごとの転送
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.40 seconds =320.00 MB/sec
 Timing buffered disk reads:  64 MB in 14.98 seconds =  4.27 MB/sec
16セクタごとの転送
[root@server]# /sbin/hdparm -t /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.40 seconds =320.00 MB/sec
 Timing buffered disk reads:  64 MB in 13.85 seconds =  4.62 MB/sec

  8%ほど向上した。あまり変わりない (^^;;

  ところで、転送できる複数のセクタ数は、個々のハードディスクなどによって
変わってくる。
  あとで紹介しますが「-i」オプションを使えば、最大転送可能なセクタ数が
出力される。

最大セクタ数の表示
[root@server]# /sbin/hdparm -i /dev/hda

/dev/hda:

 Model=Maxtor 6Y080P0, FwRev=YAR41BW0, SerialNo=Y219K6HE
 Config={ Fixed }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=57
 BuffType=DualPortCache, BuffSize=7936kB, MaxMultSect=16, MultSect=16
 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=160086528
 IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4
 DMA modes:  mdma0 mdma1 mdma2
 UDMA modes: udma0 udma1 udma2 udma3 udma4 *udma5 udma6
 AdvancedPM=yes: disabled (255) WriteCache=enabled
 Drive conforms to: (null):  1 2 3 4 5 6 7

  この場合は、16セクタのようだ。


  次に、DMAを有効にしてみた。I/Oは16ビットです。
  そして、1セクタと16セクタとの比較を行った。

DMA有効、I/O 16ビット
1セクタごとの転送
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.13 seconds = 56.64 MB/sec
16セクタごとの転送
[root@server]# /sbin/hdparm -tT /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in  1.14 seconds = 56.14 MB/sec

  ちょっと低下した。99%。
  1%の差だと測定誤差が考えられるため、同じ転送速度かもしれない。

  仮に測定誤差の範囲で、速度が変わらない場合だと、説明がつく。

  なぜなら、DMAを有効にすると、1ブロックのサイズを何セクタにしても
割り込みは最初のブロックだけ発生して、残りはDMAがCPUの代わりに
メモリ上に転送するため、CPUの負担は変わらない。
  なので、転送速度は、あまり変わらないと言える


  次に、DMAを無効にして、I/Oを32ビットにして実験をしてみた。

DMA無効、I/O 32ビット
1セクタごとの転送
[root@server]# /sbin/hdparm -t /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 15.00 seconds =  4.27 MB/sec
16セクタごとの転送
[root@server]# /sbin/hdparm -t /dev/hda

/dev/hda:
 Timing buffer-cache reads:   128 MB in  0.39 seconds =328.21 MB/sec
 Timing buffered disk reads:  64 MB in 13.89 seconds =  4.61 MB/sec

  約8%向上している。
  そういえば、I/Oが16ビットの時も、上と同じような結果だった。


  ところで、I/O転送の16ビットと、32ビットの違いが何なのか。
  どうも、よくわからないまま、ズルズルと引きずっている。


  I/Oとは、どこのI/Oを指すのか。
  そして、DMAが無効の場合だと、16ビットと32ビットの違いで
ディスクの入出力に差が出るが、DMAが有効だと差が出ないのか。
  考えてた所で、わかるわけがない。

  ふと思った。ここまで来たらヤケだ!

  IDEのドライバーソースを読んじゃえ!

  ソースを解読する実力なんて、あるわけないのに、発想だけは現実離れの
ムチャクチャな事を思いつく。


  Linux-2.4.33のソースで見てみる事にした。

  IDEのドライバーのソースコードは、drivers/ide のディレクトリーにある。
  いくつかソースを眺めてみる事にした。

  すると、PIO(DMA無効で、プログラム割り込み)の入出力の場合の
I/Oのビットの処理の部分らしき場所を見つけた。

  あくまでも「らしき」であって、断定はできないのだが (^^;;

ide-iops.c のソース
/*
 * This is used for most PIO data transfers *from* the IDE interface
 */
void ata_input_data (ide_drive_t *drive, void *buffer, u32 wcount)
{
        ide_hwif_t *hwif        = HWIF(drive);
        u8 io_32bit             = drive->io_32bit;

        if (io_32bit) {
                if (io_32bit & 2) {
                        unsigned long flags;
                        local_irq_save(flags);
                        ata_vlb_sync(drive, IDE_NSECTOR_REG);
                        hwif->INSL(IDE_DATA_REG, buffer, wcount);
                        local_irq_restore(flags);
                } else
                        hwif->INSL(IDE_DATA_REG, buffer, wcount);
        } else {
                hwif->INSW(IDE_DATA_REG, buffer, wcount<<1);
        }
}
どうやら、ほとんどのPIO(DMA無効でプログラムによる入出力)で、
IDE装置から読み込む場合の処理の部分のようだ。

ソース内の変数「io_32bit」で、「0」、「1」で16ビットか32ビットかを
判定している感じがする。
32ビットの場合、赤い部分で処理され、16ビットの場合だと青い部分で
処理されている感じだ。
そして、変数「wcount」がビット演算子で処理されている

  hwif->INSL()hwif->INSW()の違いは何か?

  それもソースの中にある。

ide-iops.c のソース
void default_hwif_iops (ide_hwif_t *hwif)
{
        hwif->OUTB      = ide_outb;
        hwif->OUTBSYNC  = ide_outbsync;
        hwif->OUTW      = ide_outw;
        hwif->OUTL      = ide_outl;
        hwif->OUTSW     = ide_outsw;
        hwif->OUTSL     = ide_outsl;
        hwif->INB       = ide_inb;
        hwif->INW       = ide_inw;
        hwif->INL       = ide_inl;
        hwif->INSW      = ide_insw;
        hwif->INSL      = ide_insl;
}
hwif->INSL()は ide_inslの事で
hwif->INSW()は ide_inswの事だ。

  だが、これではよくわからない。
  そこで「ide_insl」と「ide_insw」は何か調べてみると
同じソース内で答えがあった。

ide-iops.c のソース
static void ide_insw (unsigned long port, void *addr, u32 count)
{
        return insw(port, addr, count);
}

static void ide_insl (unsigned long port, void *addr, u32 count)
{
        insl(port, addr, count);
}

  ここで「詳解LINUXカーネル」を取り出す。
  I/Oデバイス装置の章に書いてある。

  「insl」は、CPUが連続した4バイトを複数個I/Oポートから読む込む命令。
  「insw」は、CPUが連続した2バイトを複数個I/Oポートから読む込む命令。

  つまり、CPUがI/Oコントローラ内部にあるレジスタから読み込むための命令だ。

  この場合は、CPUがIDEのコントローラー内部のレジスタにあるデータを
読む込むのだ。

  ここがhdparmの「-c」オプションで、16ビットと32ビットの違いの
核心にあたると思う。


  そういえば、16ビットと32ビットの違いがある理由に、
IDEコントローラーのチップセットの対応の問題と書いている記述があった。
  おろらく32ビットに未対応のチップセットのために、16ビットでも
データ転送を可能にしているのではないか。
  そして、PCIバスが普及する前は、IDEのハードディスクは
16ビット転送のISAバスにつながっていたため、ISAバスを使っている
マザーボードに対応するためではないかと考えられる。

  ソースがバリバリ読めるわけでもないし、ハードウェアの知識が
そんなにあるわけでもないが、推測は可能だ。


  さて、DMAが有効時には、どうなっているのだろうか。
  いくつかのソースを眺めてみたのだが、DMAに関するソースで、
16ビットI/Oと、32ビットI/Oに関する部分が見つからなかった。

  なので・・・

  事務員なのでソースは読めませーん (^^)V

  という常套手段を使おうと考えた。
  だが、ここまでくれば意地なのだ。簡単には撤退する気になれない。 

  意地になって調べてみると drivers/ide/ide-dma.c の
ソースに、データ転送のビットに関する記述らしき物を発見した。

ide-dma.c の抜粋
/*
 * Fill in the dma table, without crossing any 64kB boundaries.
 * Most hardware requires 16-bit alignment of all blocks,
 * but the trm290 requires 32-bit alignment.
 */

  このコメント分を見つけた時、「これだ!」と思った。

  「trm290」のチップ以外は、DMA転送が16ビットのようだ。

  ソースを眺めていると、どうやら、そんな感じがしてきた。
  しかし、DMA転送が16ビットだという証拠と断定する自信はない (^^;;
  何か、書物やWebサイトで記述がないかと探してみたくなる。

  ふと「チップセットの秘密」(安井健治郎:ディアート)を見てみる。

  すると本の中に以下の文章を見つける。
  「DMA転送を利用すると、常に16bitの塊でデータ転送が行われるようになる」

  これを見た時

  忍法・受け売りの術!

  と思った。
  というわけで、本の受け売りで「DMA転送が16ビットである」としておこう (^^;;
  (将来、ここの部分をコッソリと改訂していたりして)


  もし、DMA転送が16ビットなら、hdparmの「-c」オプションで、
I/Oの16ビットや32ビットの切り替えを行った所で、意味のない作業になる。

  なので、I/Oが16ビットでも32ビットでも、DMAが有効の場合、
転送速度に変化がない事が説明できる。


  ソースレベルから解説できる実力があれば、もっと核心をついた内容で
書けるのだが、私のレベルでは力尽きてしまった・・・ (--;;
  なので、I/Oの話は、この辺で終わります。


hdparmコマンドの「-i」オプション

次に、「-i」オプションをみてみます。 「-i」オプションをつければ、IDEのハードディスクの性能を見る事ができる。 早速、やってみた。
IDEのハードディスクの性能
[root@server]# /sbin/hdparm -i /dev/hda

/dev/hda:

 Model=Maxtor 6Y080P0, FwRev=YAR41BW0, SerialNo=Y219K6HE
 Config={ Fixed }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=57
 BuffType=DualPortCache, BuffSize=7936kB, MaxMultSect=16, MultSect=16
 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=160086528
 IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4 
 DMA modes:  mdma0 mdma1 mdma2
 UDMA modes: udma0 udma1 udma2 udma3 udma4 *udma5 udma6 
 AdvancedPM=yes: disabled (255) WriteCache=enabled
 Drive conforms to: (null):  1 2 3 4 5 6 7

  目が点になりそうだ。

  PIOって何?

  色々、調べて行くと、プログラマブル I/O という意味だ。

  ところで、プログラマブル I/O って何?

  プログラムで入出力(Input/Output)制御をする事だ。
  すなわちデータ転送の際、DMAを使わず、CPUへの割り込みで
データ転送を行う入出力だ。
  割り込み制御はプログラムで制御で行っている事から、
そういう名称になったと思う。

  古いIDEのディスクで、DMA転送が使えない型の物があるため、
その場合、I/OがPIOになるという。


  ところで、DMAと、UDMAがある。

  DMAとUDMA違いは何?

  という事で、調べてみる事にした。

  すると、アットマークITのサイトにDMAと対応ディスクの表があった。
  http://www.atmarkit.co.jp/fpc/pctips/032changeudmamode/changeudmamode01.html

  この表を引用し、載せてみました。

転送方式モード番号 最大転送レート対応企画
PIO モード03.33Mbytes/s
モード15.22Mbytes/s
モード28.33Mbytes/s
モード311.1Mbytes/s
モード416.6Mbytes/s
Singleword DMA モード02.08Mbytes/s
モード14.16Mbytes/s
モード28.33Mbytes/s
Multiword DMA
(MDMA)
モード04.16Mbytes/s
モード113.3Mbytes/s
モード216.6Mbytes/s
Ultra DMA
(UDMA)
モード016.6Mbytes/s
モード125Mbytes/s
モード233.3Mbytes/sUltra ATA/33
モード344.4Mbytes/s
モード466.6Mbytes/sUltra ATA/66
モード5100Mbytes/sUltra ATA/100
モード6133Mbytes/sUltra ATA/133

  IDEのハードディスクの進化の過程を見ている感じだ。
  MDMAとUDMAは、IDEハードディスクのデータ転送の規格の違いのようだ。

  ちなみに、Ultra DMA(Ultra ATA)は、E-IDEの規格を拡張した物だという。


  さて、もう一度、hdparmコマンドの「-i」オプションの結果を見てみる。

IDEのハードディスクの性能
[root@server]# /sbin/hdparm -i /dev/hda

/dev/hda:

 Model=Maxtor 6Y080P0, FwRev=YAR41BW0, SerialNo=Y219K6HE
 Config={ Fixed }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=57
 BuffType=DualPortCache, BuffSize=7936kB, MaxMultSect=16, MultSect=16
 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=160086528
 IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4
 DMA modes:  mdma0 mdma1 mdma2
 UDMA modes: udma0 udma1 udma2 udma3 udma4 *udma5 udma6 
 AdvancedPM=yes: disabled (255) WriteCache=enabled
 Drive conforms to: (null):  1 2 3 4 5 6 7

  このハードディスクの場合、UltraDMAの転送モードが「5」になっている。

  ところで転送モードは、ハードディスクだけでは決まらない。
  マザーボードについているIDEコントローラーの種類にも依存している。
  ソフトウェアがハードディスク本体と、IDEコントローラーを見て
最適だと思った物を選ぶ。

  この場合、UltraDMAの転送モードが「5」が最適だと判断しているのだ。

  もちろん、ソフトウェアが選択するのが正しいとは限らない。
でも、転送モードの変更は可能だ。

  hdparmコマンドの「-X」オプションを使えば変更できる。

  「-X69」だと、UltraDMAの転送モードが「5」だという。
  「-X68」だと、UltraDMAの転送モードが「4」だという。

  なんだか、難しい感じがした。
  暗記の嫌いな私にとっては

  そんな個々の設定方法なんて覚えられるかい!

  と思った。
  だが、manで調べてみると、キチンと説明が書いてあった。

man hdparmの結果
-X     Set the IDE transfer mode for newer (E)IDE/ATA2 drives.  This is  typically  used
       in  combination  with -d1 when enabling DMA to/from a drive on a supported inter-
       face chipset, where -X34 is used to select multiword DMA mode2  transfers.   With
       systems  which  support  UltraDMA  burst timings, -X66 is used to select UltraDMA
       mode2 transfers (you'll need to prepare the  chipset  for  UltraDMA  beforehand).
       Apart  from  that, use of this flag is seldom necessary since most/all modern IDE
       drives default to their fastest PIO transfer mode  at  power-on.   Fiddling  with
       this  can be both needless and risky.  On drives which support alternate transfer
       modes, -X can be used to switch the mode of the drive only.   Prior  to  changing
       the  transfer  mode,  the  IDE interface should be jumpered or programmed (see -p
       flag) for the new mode setting to prevent loss and/or corruption  of  data.   Use
       this  with extreme caution!  For the PIO (Programmed Input/Output) transfer modes
       used by Linux, this value is simply the desired PIO mode number plus 8.  Thus,  a
       value of 09 sets PIO mode1, 10 enables PIO mode2, and 11 selects PIO mode3.  Set-
       ting 00 restores the drive's "default" PIO mode, and 01 disables IORDY.  For mul-
       tiword DMA, the value used is the desired DMA mode number plus 32.  for UltraDMA,
       the value is the desired UltraDMA mode number plus 64.
赤い部分がPIOでの転送モードの指定の場合だ。
転送モードの数字に「8」を足した物になる。
もし、PIOのモード「2」を選びたい場合は、オプションは「-X10」になる。

青い部分がMDMAの転送モードの指定だ。
「-X」の後ろの数字は、転送モードの数字に「32」を足した物
もし、MDMAのモード「1」を選びたい場合は、オプションは「-X33」になる。

ピンクの部分は、UDMAの転送モードの指定だ。
「-X」の後ろの数字は、転送モードの数字に「64」を足した物
もし、UDMAのモード「5」を選びたい場合は、オプションは「-X69」になる。

  なるほど、これだと暗記にならない!

  ただし、この設定は私はしない。
  なぜなら、下手な事をしてハードディスクが壊れたりしたら大変だからだ。
  まぁ、何も触らないのが無難かもしれない (^^;;



hdparmコマンドの「-I」オプション

さて、「-I」オプションについて説明します。 さきほどの「-i」オプションよりも詳細な情報を見るための物だ。
IDEのハードディスクの性能
[root@server]# /sbin/hdparm -I /dev/hda

/dev/hda:

ATA device, with non-removable media
        Model Number:       Maxtor 6Y080P0                          
        Serial Number:      Y219K6HE            
        Firmware Revision:  YAR41BW0
Standards:
        Supported: 7 6 5 4 
        Likely used: 7
Configuration:
        Logical         max     current
        cylinders       16383   16383
        heads           16      16
        sectors/track   63      63
        --
        CHS current addressable sectors:   16514064
        LBA    user addressable sectors:  160086528
        device size with M = 1024*1024:       78167 MBytes
        device size with M = 1000*1000:       81964 MBytes (81 GB)
Capabilities:
        LBA, IORDY(can be disabled)
        Queue depth: 1
        Standby timer values: spec'd by Standard, no device specific minimum
        R/W multiple sector transfer: Max = 16  Current = 16
        Advanced power management level: unknown setting (0x0000)
        Recommended acoustic management value: 192, current value: 254
        DMA: mdma0 mdma1 mdma2 udma0 udma1 udma2 udma3 udma4 *udma5 udma6 
             Cycle time: min=120ns recommended=120ns
        PIO: pio0 pio1 pio2 pio3 pio4 
             Cycle time: no flow control=120ns  IORDY flow control=120ns
Commands/features:
        Enabled Supported:
           *    NOP cmd
           *    READ BUFFER cmd
           *    WRITE BUFFER cmd
           *    Host Protected Area feature set
           *    Look-ahead
           *    Write cache
           *    Power Management feature set
                Security Mode feature set
                SMART feature set
           *    FLUSH CACHE EXT command
           *    Mandatory FLUSH CACHE command 
           *    Device Configuration Overlay feature set 
           *    Automatic Acoustic Management feature set 
                SET MAX security extension
                Advanced Power Management feature set
           *    DOWNLOAD MICROCODE cmd
           *    SMART self-test 
           *    SMART error logging 
Security: 
        Master password revision code = 65534
                supported
        not     enabled
        not     locked
        not     frozen
        not     expired: security count
        not     supported: enhanced erase
HW reset results:
        CBLID- above Vih
        Device num = 0 determined by CSEL
Checksum: correct

  最初、上の出力結果を見た時・・・

 完全に目が点になった  (・・)

  でも、慣れてくれば、色々なハードディスクの設定状態が見えてくる。
  ハードディスクの勉強には使えるオプションだ。

  ここでは軽く触れる程度で終わります。

hdparmコマンドの「-W」オプション

「-W」オプションだ。 これは、ハードディスクの磁気円盤に記録する前に、ハードディスク内部の メモリに書き込むためのオプションだ。 ハードディスク内部には、メモリも搭載されている。
ハードディスク内部のキャッシュメモリ
ハードディスク内部のキャッシュメモリの図
ハードディスクの内部には、データを記録する磁気円盤以外にも、
メモリを積んでいる。

もし、メモリがなければ、直接、磁気円盤に記録されるのだが、
磁気円盤への書き込み速度は遅い。
OSは、書き込み速度に合わせてデータ送信を行うため、
書き込み処理に時間がとられ、書き込み性能が悪くなる。
そこで一度、メモリにデータを入れて、その後、ハードディスク側で
磁気円盤に記録すれば、OSは書き込み処理に追われなくなるという。

それに、前ぶれもなく、いきなりデータを送っても、
円盤に記録するアームの移動などで時間がかかる(シーク時間)ため
一度、メモリにデータを保管して、そこから磁気円盤に記録するという
仕組みなのだ。

洪水の時に、いきなり川に水を流すのではなく、ため池に入れて
流すのと同じ原理だ。

  このキャッシュメモリの量だが、個々のハードディスクによって違う。
  さて、「-i」オプションで見てみる事にした。

IDEのハードディスクの性能
[root@server]# /sbin/hdparm -i /dev/hda

/dev/hda:

 Model=Maxtor 6Y080P0, FwRev=YAR41BW0, SerialNo=Y219K6HE
 Config={ Fixed }
 RawCHS=16383/16/63, TrkSize=0, SectSize=0, ECCbytes=57
 BuffType=DualPortCache, BuffSize=7936kB, MaxMultSect=16, MultSect=16
 CurCHS=16383/16/63, CurSects=16514064, LBA=yes, LBAsects=160086528
 IORDY=on/off, tPIO={min:120,w/IORDY:120}, tDMA={min:120,rec:120}
 PIO modes:  pio0 pio1 pio2 pio3 pio4
 DMA modes:  mdma0 mdma1 mdma2
 UDMA modes: udma0 udma1 udma2 udma3 udma4 *udma5 udma6 
 AdvancedPM=yes: disabled (255) WriteCache=enabled
 Drive conforms to: (null):  1 2 3 4 5 6 7

  どうやら、このハードディスクは8M近くのキャッシュメモリを積んでいる。

  ちなみに、1997年に購入したパソコンのハードディスクの場合、
たった128Kバイトだった。えらい違いだ。


  初期状態では、どうなのだろうか。
  まずは、「-I」オプションで、ハードディスクの状態を見てみる事にした。

「-I」オプションの結果の抜粋
[root@server]# /sbin/hdparm -I /dev/hda

(途中、省略)

Commands/features:
        Enabled Supported:
           *    NOP cmd
           *    READ BUFFER cmd
           *    WRITE BUFFER cmd
           *    Host Protected Area feature set
           *    Look-ahead
           *    Write cache
           *    Power Management feature set

(途中、省略)

  キャッシュが有効になっている。
  そこで、「-W」オプションで、キャッシュを無効にしてみる。

「-W」オプションを実行
[root@server]# /sbin/hdparm -W 0 /dev/hda

/dev/hda:
 setting drive write-caching to 0 (off)

  そして、ハードディスクの状態を見てみる。

「-I」オプションの結果の抜粋
[root@server]# /sbin/hdparm -I /dev/hda

(途中、省略)

Commands/features:
        Enabled Supported:
           *    NOP cmd
           *    READ BUFFER cmd
           *    WRITE BUFFER cmd
           *    Host Protected Area feature set
           *    Look-ahead
                Write cache
           *    Power Management feature set

(途中、省略)

  見事に無効になっている。


  書き込みキャッシュだが、良い面ばかりではない。
  もし、キャッシュからハードディスクにデータが書き込まれる前に
不意にパソコンの電源が落ちたりしたらどうなるのか。

  もちろん、データはオシャカになる!

  その危険性は、頭に入れて置いた方が良いと思う。


  ところで、書き込みキャッシュの有効・無効について、Windows98と
WindowsXPでも、同じような設定がないかと思って見てみた。
  するとあった!

Windows98
Windows98のキャッシュへの書き込みの有無の設定画面
赤い部分が該当の箇所だ。
初期状態ではキャッシュへの書き込みが有効になっている。

  こんな事、今まで知らなかった (^^;;

  お次は、WindowsXPだ。

WindowsXP
WindowsXPのコンピューター画面
青い部分のディスクドライブで、プロパティーを見る。

  すると、以下の画面が出てくる。

WindowsXPのキャッシュ書き込みの有無の設定
WindowsXPのキャッシュ書き込みの有無の設定画面
赤い部分が該当の箇所だ。
初期設定ではキャッシュへの書き込みが有効になっている。

  Windowsのクライアントで、こんな制御ができるとは知らなかった。
  これを見る限り、Windowsを使いこなすのも、相当、知識が必要だと思う。

  LinuxもWindowsも、ハードウェアの情報が見れるので、勉強になる。

まとめ 他にも、hdparmのオプションはありますが、キリがない上、 下手に触ると危険な物までありますので、この辺で終わる事にしました。 ハードディスクですが、今までは容量以外、何も気にとめていませんでしたが 今回の事で、知らない事がボロボロと出てきました。 おまけに、ハードウェアの知識がない事も露呈しました。 というわけで、今回、私が学んだ事を挙げてみました。
私が学んだ事
(1) DMAは有効にした方が速い!
(2) 先読みセクタ数は、個々の場合によって最適値が変わってくるため
「これが一番」という値は、自力で見つける以外はない。
(3) IDEよりSCSIの方が誤り訂正がある分、データの信頼制が高い
(4) メモリのECCの有無は、メモリのデータの誤り訂正の有無
(5) DMAが有効だと、「-c」オプションで32ビット転送にしても効果なし
(6) Windowsでもハードウェアの制御ができる!

  だが、課題も出た。

  マザーボードの知識がない事やハードウェアの知識がない事も出た上、
割り込みの仕組みや、DMA転送の仕組みが、あまり理解していない事だ。

  まぁ、それは勉強していけば良いのだから、前に進もう! (^^)

  知らない事がボロボロ出たので、システム奮闘記の初期の頃を思い出す。
  初心を思い出すなぁ。

次章:「FPDFで無料PDF帳票システム構築」を読む
前章:「ライブラリの役目と利点」を読む

目次:システム奮闘記に戻る

Tweet