本当に初心者の人に捧げるコンピューター入門

もう少し突っ込んだハードウェアの話


 さて、前のまとめで次にOSの話をすると書きましたが、そのためにはもう少し実際のコンピューターのハードウェアについて知っておく必要があります。
 といってもCPUの内部構造云々などという話ではなく、CPUとメモリー、外部入出力装置などが、実際にどのようにつながっているか、という話です。今後OSの話をするにあたって、このあたりが分からないと結構厳しいのでここで簡単に説明しておきます。


もう少しまともに書いたコンピューターの構成



 以前に大変手抜きで書いたコンピューターの図を載せましたが、今度はもう少し力を入れて書いてみましょう。

もう少しましなハードウェアの図

この絵を別ウインドウで開く

(スクリーンの幅が広い人は開いておくと以下の説明が見やすいです)


 何か少し色が付いてきれいになってますが、本質的なところは大差ないですね。
 CPUにメモリーと外部入出力装置(今回は実際の名前を書いてます)がつながっているところは同じです。
 大きな違いといえば、CPUと外部入出力装置やメモリーの間をつなぐ線が少し複雑になっているところです。
 言い換えれば実際のコンピューターでは各機器間のデータや信号の流れが、以前の手抜きの図に比べてもう少し複雑になっているということです。

  • 筆者は絵が描けないので、これに見合った人の絵はなしです。

バス



 まず注意して欲しいのは、各装置をつなぐ赤と青の太い線です。

 この線のことをバスといって、コンピューター内部の信号伝達経路です。一般社会における交通網に相当します。
 赤い線はアドレスバスといって、各装置にCPUがデータを要求するときに使います。青い線はデータバスといって、各装置からCPUまたはCPUから各装置に実際にデータを転送するとき使われます。
 コンピューターは様々な装置がこのバスで連結されて構成されているとも言えます。

 ここで重要になってくるのが、このバスのデータ転送速度です。
 ちょっと考えたら分かるとおり、個々の装置がどれほど高速に処理を行えたとしても、もしこのバスのデータ転送速度が遅かったらどうしようもありません。そのため原則としてはバスの性能は高ければ高いほど良いわけです。

 しかしバスが高性能になると困ったことも起こります。例えば高性能になればなるほど使うのに神経が必要です。いい加減に作った装置だと、その高速性に付いていけなくなってデータ転送に失敗してしまうかもしれません。がんばってそういう装置を作ったら、その結果は値段に反映してしまうかもしれません。

 こういう場合どうすればよいでしょうか?それは本当に必要なところだけ高性能な物を使って、他のどうでもいいところは低速だが安いバスを使うことで回避できます。
 例えばメモリーからのデータを読み書きするためには、転送速度は速ければ速いほどいいでしょう。しかしキーボードからのデータのやりとりにはそんな高速性は必要ありません。たいていの人はそんなに速くキーボードを打てないからです。

 そのため上記の図ではメモリーから何から含めて一本のバスとして書かれていますが、実際のハードウェアには用途に応じて様々な種類のバスがあります。
 そして注意しなければならないのは、各外部入出力装置はそれぞれどのバスに対応して作られたかが決まっていることです。あるバスに対応して作られた装置はまず他のバスに接続することはできません。

 以下は結構普通のコンピューターに使われていて、みなさんに関係しそうなバスの種類です。

ISAバス昔からあったバスで今となっては比較的低速な装置と接続するのにしか使えない。といっても結構大抵の物に使えますが。
PCIバス比較的新しい種類のバスで、ISAバスより高速な外部入出力装置と接続できる。今は大は小を兼ねるで遅くて良い機器でもこれ対応の物が多くなっている。
AGPバス最近できたものでグラフィックカード専用にチューニングされたバス。
USBバス最近できたもので、キーボードやマウス、ディスプレイなどをまとめてつなぐのに便利なバス。


CPU−メモリー間のデータのやりとり



 まず最初に一番重要なところ、CPUとメモリー間のデータ転送について説明します。

 CPUがメモリーを読み書きしたいときには、機械語ではメモリーの番地を指定して、そこを読むとか書くとかしていました。
 実際のハードウェアでは、CPUがメモリーを読みたい場合は(すなわちメモリーのデータを読めという機械語命令が実行された場合)まず赤い矢印のアドレスバスにデータを読みたいんだ!という信号と、読みこみたいデータの入っているアドレスを送ります。
 するとメモリー(のハードウェア)はそれを解釈して指定されたアドレスのデータを、青の矢印で示したデータバスに書き込みます。
 CPUはそれを読むことで、メモリーの読み出しは終了です。

 メモリーに書き込みたい場合もほぼ同じです。
 CPUはアドレスバスにデータを書き込みたいんだ!という信号と、書きこみたいアドレスを送ります。その後CPUはデータバスに書き込みたいデータそのものも書き込みます。
 メモリーはそれを見て指定されたアドレスにデータを書き込みます。

 青の矢印が双方向に付いているのは、このように読むときも書くときも同じデータバスが使われるからです。


キャッシュって?



 ところでCPUとメモリの間にキャッシュというのが挟まっています。これはなんでしょう?
 これはメモリのアクセスを効率化するための仕組みです。昔のコンピューターはCPUの速度が遅かったのでこんな仕組みを入れる必要はありませんでしたが、今はほとんど必須な物になっています。

 CPUが実行する命令は前にも書いたとおりメモリーの中に書かれており、それを順番に読んで実行するわけです。
 ところが、以前補足でもちょっと書きましたが、現在のハードウェアでは、CPUの速度に比べてメモリーアクセスの速度はかなり遅いのです。
 こうなるとどうでしょう?CPUの速度がいくら速くても、肝心の命令とデータがやってこなければどうしようもありません。結局CPUがどれだけ速くとも、メモリー転送速度以上の速度は出せないことになります。

 これを回避するために現在のハードウェアにはまず大抵CPUとメモリーの間にキャッシュメモリーという物を挟んでいます。
 キャッシュメモリーは容量はあまりありませんが、とにかく高速に読み書きできるという特徴を持っています。

 そこでメインのメモリーからデータを読むときにはまず、メインメモリーからキャッシュメモリーにもデータを転送します。
 次にCPUがメモリーからデータを読み出したいときには、まずキャッシュメモリーの中を調べて、そこに既にデータが存在すれば、キャッシュメモリーからデータを読みます。そこになかったときだけメインメモリーにアクセスします。

 こうすることで、あるメモリーのエリアを読むときは1回目だけは確かに遅いですが、2回目以降の読み込みは非常に高速になります。
 実際のプログラムでは結構同じ所のデータを読み書きすることが多いので、こうすることによってコンピュータの実行速度が上がるのです。

 これはメモリーアクセスに限らず、読み書きの遅い装置からのデータ入出力を効率化するために、非常によく使われる手法です。


CPU−外部入出力装置間のデータのやりとりの概要



 さてそれではCPUは外部入出力装置とどうやってデータのやりとりをするのでしょう?
 そのやり方は大きく分けて3通りあります。

  1. I/Oポートを利用するデータ入出力
  2. ダイレクトメモリーアクセス
  3. 共有メモリを利用するデータ入出力

 これらはそれぞれ長所と短所があるので、各装置ではその装置に要求される性能を元に、上記の3種類を使い分けています。

 以下順番に説明していきましょう。


I/Oポートを利用するデータ入出力



 まずもう一度上の図を思い出して下さい。見て頂いたら分かるように、外部入出力装置にもアドレスバスがつながっています。このつながっている出入り口の部分をI/Oポートと呼びます。
 外部入出力装置はI/Oポートを介してメモリーアクセスと似たようなやり方でデータのやりとりができます。

 CPUが外部入出力装置とデータをやりとりするためには、まずどの装置とデータをやりとりするのかが分からなければなりません。
 そのために各装置のI/OポートにI/Oアドレスという番号を振ります。これは1装置に1個と決まってるわけではなく、いくつでも割り振れます。
 ただし当然のことですが、1個のアドレスを複数の装置に割り当てることはできません。そんなことをしたらどうなるか、ちょっと考えれば分かりますね?

 CPUがデータを読み出したいときは、I/Oポートのアドレスバスにデータを読みたいんだ!という信号と、データを読み込みたい装置のI/Oポートアドレスを送ります。
 各装置は自分のアドレスが来たら要求されたデータを、青の矢印で示したデータバスに書き込みます。
 CPUはそれを読むことで、装置からのデータの読み出しは終了です。

 装置にデータを送りたい場合もほぼ同じです。
 CPUはアドレスバスにデータを送りたいんだ!という信号と、相手の装置のI/Oアドレスを送ります。その後CPUはデータバスに書き込みたいデータそのものも書き込みます。
 各装置はそれを見て自分宛のデータであれば、データバスからデータを読み込みます。

 このやり方の長所は、最も構造的にシンプルだということです。多くの装置は大抵これしか付いていなかったりします。
 またそうでない装置でも、装置のコントロールをするためには普通はこのやり方を使います。


ダイレクトメモリーアクセス



 外部入出力装置の中には、単にデータを一気にメモリーに読み書きしたいという物も多く存在します。
 例えばハードディスクなどの装置を扱う場合は、ほとんどの場合データを一気にメモリーに読み込んで、それからゆっくり処理をすると言う手順となります。
 上のI/Oポートを利用するやり方では、データを転送する際には必ずCPUを介して行われていました。これは当然その分手間がかかります。

 また上の図を見てもらうと、データバスは必ずしもCPUを介さなくてもメモリーに直結できるように書いています。これは実際にそういうことが可能なのでそう書いているわけです。

 このように外部入出力装置からメモリーに直接データを書いたり読んだりする仕組みをダイレクトメモリーアクセスと呼びます。

 この方法をよく使うのは、ハードディスクなどです。


共有メモリを利用するデータ入出力



 データ入出力には更に別な方法も考えられます。
 また上の図を見てみて下さい。よく見るとCPUとメモリーの接続もCPUと外部入出力装置の接続も同じような矢印でつながっています。これは手を抜いて書いたからそうなったのではなく、機能が実際に似ているからそう書いているのです。

 ということはどういうことかというと・・・外部入出力装置にメモリーの真似をさせることも可能だということなんです。

 ある一定エリアのメモリー領域があります。これは通常はメインのメモリーに接続しているのですが、これを切り替えて外部入出力装置に割り当ててしまうということが可能なのです。

 こうすると外部入出力装置とのデータのやりとりは、メモリーをアクセスするのと同じ方法で行えることになります!

 この方法を最もよく使う装置はグラフィックカードなどです。

 というわけで大ざっぱに3種類のデータ入出力方法について説明しました。 これでめでたくこの章は終わりかというと・・・実はそうは問屋が卸しません。


割り込み



 確かに原理的には上記の仕組みだけで十分なのですが、これだと実際上の効率が悪い場合が多いのです。
 
上の図をよく見て下さい。データバスとアドレスバスのつながりだけを見ると、CPUがデータを要求したり送ったりすることはできますが、外部入出力装置の方から自発的にデータを送るということができません。

 これがどういう問題になるかというと・・・例えばあなたの家の電話にはかかってきたら相手が液晶モニタに表示される機能が付いていたとします。ここで子供が暴れたか何かの理由で、電話のベルが壊れて鳴らなくなったと仮定しましょう(今時ベルかい!という突っ込みは却下)

 この電話機は使えるでしょうか? もちろん答えは

「絶対使えないとは言わないが、そんなもんは速攻で捨てる」

ですね。
 絶対使えない訳ではない理由は、ずっと液晶モニタを見ていればベルが鳴らなくとも電話がかかってきたことは分かるからです。

 でもはっきりいって滅茶苦茶うっとうしい話です。夜中も電話を見張るためだけに起きてなければなりません。その上相手がある程度気長で、呼び出し音を何百回も鳴らしてくれるような人でないと、発見し損なう確率も高いです。

 外部入出力装置とのやりとりが、以上の手段だけだったとしたら、以上のことに大変よく似たことが起こります。

 例えばマウスがあります。当たり前ですが、マウスを動かすとマウスカーソルも動きます。
 これを上記の手段だけで実現しようとするとどういうことになるでしょう?

 これはプログラム上から頻繁にマウスに対して「今動いたか?」と問い合わせをするしかありません。なぜならCPUからデータを寄こせ!という指令が来ない限り、各装置はCPUに対しては何もしないからです。
 こうすることでとりあえずマウスを動かしたらマウスカーソルも動く、という動作は実現できます。コンピューターはだからといって文句をたれたりはしません。

 しかし、たかがマウスが動いたかどうかを監視するためだけにCPUパワーを使うのは、効率が悪すぎます。外部入出力装置はマウスだけではありません。それら全てを見張っているのでは、いかな高速のCPUといえど、本当にやらせたい仕事に使えるパワーがかなり減ってしまうでしょう。

 外部入出力装置にはいろいろな種類があります。中には頻繁にデータのやりとりが必要な物もありますが、多くは滅多にデータのやりとりなど発生しません。
 例えばキーボードにしたって、ほとんどの人は滅多に叩かないのではないでしょうか?

 とするとそれら全てをいちいちCPUが見張るのではなく、データのやりとりの必要が発生したときに割り込んでCPUに通知してやる仕組みがあれば便利だという結論になります。
 さっきの例でも、電話のベルがちゃんとしていれば、電話なんてかかってきたときだけに思い出せばよい存在です。そんなことで睡眠時間を削られなくて済んだわけです。

 上の図に赤の細線で外部入出力装置からCPUに向かっているのがその仕組みで、名前もそのものずばりの割り込み(Interrupt Request 略して IRQ)といいます。
 この仕組みがあればCPUは割り込み信号が来たときだけ、該当する装置とデータのやりとりをすればいいわけです。

    ・・・とまあ「ずっと見張る」という方法に関してさんざん悪口を並べてきましたが、これはこれで使える方法でもあるのです。というのは、割り込み処理というのはプログラムするのが意外に面倒だからです。だから非常に多くの場所でこの手法は積極的に使われています。みなさんにはあまり関係のない話ですが・・・ついでながら、この手法のことをポーリングと言ったりします。
 ちなみに細かい話ですが、割り込みには優先順位を設定することができます。なんでかって?

 特に重要な仕事をしたいときに割り込まれたら困ることは十分考えられます。例えば非常に短い時間の間に結構な処理を終わらせなければならないようなことはよくあります。そういうときに勝手に割り込まれて、せっかくの作業がおじゃん!っていうのは困りますね?
 そのためCPUも一時的に割り込みを禁止する機能を備えています。

 しかし時と場合によりけりです。例えばあなたが秘書に「今日は忙しいから外からの電話は取り次がないでくれ」と指示したとします。やっと仕事が終わって帰ろうとしたときに、秘書から「あの、お昼頃奥様が車にはねられて亡くなられたという電話がありました」なんて言われたら・・・もちろんあなたにはその秘書を好きにする権利があります。

 というわけで、コンピューターの世界の割り込みも「とにかく絶対!」というのから「まあ気が向いたら」というところまで何段階かの優先順位が設定できます。そして割り込みを禁止するときも「ここのレベルまでは禁止!」という指定ができるわけです。
  • 以前の補足にこっそりとあった割り込みモードとは、割り込みの優先順位のことで、ノンマスカラブル割り込みというのは、とにかく無条件に実行される割り込みのことです。コンピューターにとって命に関わるような問題とは、例えばノートパソコンの電池が切れかかってるとかいったものがあります。

 次章からはやっとOS編に突入します。



前へ 目次へ 次へ