[パタヘネ:読書メモ]第6章 ストレージおよびその他の入出力の話題

6.1 はじめに

6.2 信頼性と信頼度とアベイラビリティ

6.3 ディスク・ストレージ

6.4 フラッシュ・ストレージ

6.1~6.4の内容は基本的な事項なので省略
(応用情報処理の試験とかのレベル)


6.5 プロセッサ、メモリ、入出力装置間の接続


プロセッサ、メモリ、入出力装置間はバスで接続されている。
バスのメリットは、汎用的で低コストということ。

バスは大きく3つに分かれる。

プロセッサ-主記憶間バス
    最も距離が短く、最も速くする必要がある。
 
入出力バス
    距離が長く、複数のデバイスが接続される。
    I/Oが直接メモリに接続されるわけではなく、他のバスを経由して接続される。
 
バックプレーンバス
    単一のバスに、メモリ、I/Oを両方接続できるようにしたもの



バスは、信号線の物理的な距離や、最大接続数の制限が掛かる場合がある。


昔のバスは、クロックに同期してデバイスが動作していた。同期式メリット、デメリットには以下の点があげられる。

メリット
    ハードの設計が簡単
    高速に動作できる
デメリット
    バス内の各デバイスが同じクロックになること
    信号線が長くなるとクロックの遅延(クロックスキュー)が発生する



プロセッサが高速になるとデメリットが問題になってくるため、近年では非同期式のインターフェースが使用される事が多い。USB2.0,S-ATA,SAS,PCI Expressなどは全て非同期式になっている。

最近のPCで使用されているIntelやAMDのCPUでは、バスが上流(CPU寄り)と、下流で2つに別れている。
上流側のバスを管理しているのがノースブリッジというチップセット(LSI)で、メモリやPCI Expressのバスを管理している。こちらは短距離な配線で小数のデバイスが高速に動作している。

下流側は、サウスブリッジで、ディスクや、キーボード、マウス、USBなど低速なデバイスが多数接続される。


6.6 プロセッサ、主記憶、OSと入出力装置のインタフェース


というわけで、バスを通して入出力装置(I/O)が接続されることとなった。
これでCPUはI/Oとデータの受け渡しが可能になるけど、以下の考慮点がある。

1. メモリとI/O間でのデータ転送はどのように実装されるのか?
2. I/Oが要求するデータ送受信コマンドを誰が生成するか?
3. I/O処理において、OSは何をしているのか?



OSはI/Oとのやり取りに対して、以下の前提を置いている。

I/Oは複数のプログラムで共有される。
    -> OSはプログラムからのI/Oアクセスをコントロールしている
 
I/Oはデータの送受信に関して、割り込みを使ってCPUにトリガを発している。
    (割り込みは、一般にユーザモードではなくシステムモードで動作するので、OSやVMMの範疇となる)
    -> I/O割り込みはOSがトラップする
 
I/Oの制御は、時に複数のデバイスを同時に処理する必要があり、
またタイミングの問題もある為、管理が煩雑になる。
    -> デバイスやプロセスのスケジューリングはOSの主要な役割の1つ




I/Oへのコマンド送信

外部デバイスとのやり取りを行うためには、デバイスへのコマンド(データ)送受信が必要となる。
このコマンド送受信には2つの方式がある。

メモリマップドI/O
    メモリ空間上にI/Oデバイスを割り当てる
    (CPUから見ると特定アドレスにメモリ書き込み命令を行うと、バス経由でI/OがコマンドをReadする)
 
入出力用特殊命令
    I/O処理用を行う専用の機械語命令をCPUに持たせる




入出力用特殊命令の例としては、例えばIntelの8080(8086より前にでたCPU)では、IN命令/OUT命令というオペコードが存在している。


メモリマップドI/OのほうがCPU設計的にはシンプルになる。一方、入出力用の特殊命令があるとメモリ空間とI/O空間が分離できるので、メモリをフルに認識できる。
※例えば、Windows XPや7の32bit版では、最大搭載メモリが4GBなのに、認識可能なメモリサイズが3GB程度という制限が有った。もし入出力用の特殊命令を使用していたら4GB全てを認識できたはず。


I/Oとの通信には、以下の2つの方式がある。

ポーリング方式
割り込み方式



ポーリング方式は、CPU側がI/Oの状態を一定周期で監視する方法となる。
これは、擬似コードで書くと以下のようなイメージになる。

while( 1 ) {
    I/Oの状態をread
    if ( I/Oの状態を変わったら ) {
        何かをする
    }
 
    ...他の仕事を行う...
}



この方法は簡単だけどCPUサイクルの無駄遣いに繋がる。I/OはCPUに比べてとても遅いので、状態チェックをすべき状況に至ってから、期待する状態変化が起こるまで非常に長い時間が掛かるのが無駄が出る原因となっている。

なので、最近のCPUは割り込み方式でI/O制御を行う事が多い。
これは、I/Oの状態が変化したタイミングで、CPUに割り込みをかける。ポーリングに比べて割り込みのほうが、CPUはI/O側の処理が完了するまで非同期で他の仕事を行えるため、効率が良い。



割り込み処理を採用する場合、以下の点に注意が必要となる。

1.基本的に割り込みは非同期処理になる。
(CPUサイクル的に見て)割り込みが掛かった瞬間に、ソフトウェアはそのことを認識できるわけではなく、
I/Oが割り込みを立ててから、CPUが割り込み線を見るまでの遅延は存在する。
※もちろんこの遅延が発生したところで、ポーリング処理にに比べれば、断然CPU処理の無駄や
レイテンシは少ない
 
2.割り込みは複数発生するし、同時に発生する事がある。
CPU/ソフトウェアは優先順を決めて処理を行っていく必要がある。
また、CPUは何の割り込みが掛かったかを識別できる必要がある。
(MIPSではCAUSEレジスタで割り込み理由が識別できる)
 
 
3.割り込み中に割り込みが掛かる可能性もある
"割り込み中の割り込み"を処理すべきかどうかの配慮が必要。
これを認めないと処理は簡単になるけど、大事な処理が遅延するリスクがある。
逆に認めると、ソフトウェア的な制御が難しくなる。
(通常は、今処理している割り込みより優先度が高い割り込みだけ、多重割り込みを認める)





割り込み処理の実装

割り込み処理の実装は当然ソフトウェアによって異なるが、UNIXの場合、優先度が4~6レベルに分類されており、以下の特性を持つ。

入出力例外より、内部例外のほうが優先度が低い
入出力例外では、遅いデバイスのほうが優先度が低い



割り込み優先度の管理を行うためのサポートをMIPSでは行っている。
この為に、指定以上のレベルの割り込みのみを受け付けたり、割り込み理由の通知を行ってくれるレジスタを用意している。



ポーリングや割り込みは、どちらもCPUとI/O間の通信方法の仕組みだけど、都度CPUが関与する必要がある為、負荷が高い(=低速デバイス向けとなる)

一方でディスク-メモリ間のデータ転送などの場合は、kbyte単位のオーダーで転送が掛かる場合もある為、いちいちCPUが関わっていては遅くなってしまう。
この為、DMA(Direct Memory Access)を使って、ディスクとメモリ間のデータ転送をCPUが関与せずに行う仕組みをとる。

この場合、データ転送中は当然ながらCPUがバスを使用することが出来なくなる為、バスの占有権の管理が必要となってくる。
DMA転送を行う場合、DMAコントローラーというものを追加でバスに設ける。CPUやDMAコントローラーなどのバスを主体的に使う側のコントローラーを、バスマスタと呼ぶ。

DMA方式でデータの転送を行う場合、CPUとDMAコントローラは、以下の手順でやり取りを行う。

CPUはDMAコントローラに,データ転送要求を行う。
要求には通常、以下のような情報が含まれる
    入出力装置のデバイスNo
    read/writeの区分
    データ転送元アドレス
    データ転送先アドレス
    データ転送サイズ
 
DMAコントローラは、バスに存在する他のバスマスタに、バスの占有権を主張する。
 
DMAコントローラは、(Readの場合は)入出力装置からデータをReadし、メモリの指定された位置にWriteする。
(Writeの場合も方向が逆になるだけで同様)
 
 
DMAコントローラは、データ転送が完了するとCPUに外部割込みをかける。
 
CPUは、データ転送が終わった事を認識し、後続の処理を行う。



バスアーキテクチャによっては、DMAコントローラーは1つだけとは限らず、複数の場合もありえる。


もちろんDMA転送中にCPUがメモリアクセスが必要な場合はDMA待ちになってしまうが、キャッシュが効いていれば、ある程度はCPU内だけで他の処理を続ける事も可能となる。(というか、キャッシュのおかげでCPUが非同期処理できるので、DMAの価値が出てくる)


DMAコントローラは単なるメモリ操作を行うものだが、もう少し多機能なものもあり、これは”入出力プロセッサ”と呼ばれる場合もある。


関連記事

コメントを残す

メールアドレスが公開されることはありません。