見出し画像

伝説の書『MS-DOSエンサイクロペディア』Vol.1 を読み解く その5:「キャラクタデバイス」って何?

伝説の書『MS-DOSエンサイクロペディア』Vol.1を読み解くシリーズ。ボチボチですが、今回も続けていきます!前回の「EXEとCOM、そしてPSPの正体」に続き、今回は「第5章 キャラクタデバイスの入出力」を紐解いていきましょう。

伝説の書『MS-DOSエンサイクロペディア』Vol.1 を読み解く その4:EXEとCOM、そしてPSPの正体

そもそも「キャラクタデバイス」って何?

MS-DOSが扱うデバイスには、大きく分けて次の2種類があります。

  • ブロックデバイス:ディスクなど、一塊(セクタ単位など)のサイズでデータをやりとりするもの。

  • キャラクタデバイス:キーボードや画面のように、データを1文字(1バイト)ずつリアルタイムにやりとりするもの。

今回は、この「キャラクタデバイス」の進化の歴史を見ていきます。

MS-DOS Ver.1時代からの「4大標準デバイス」

Ver.1の時点では、あらかじめ以下の4つのキャラクタデバイスが標準で用意されていました。

  • CON(コンソール)
    役割: 画面出力およびキーボード入力。
    用途: COPY CON FILENAME.TXT と入力して、キーボードから直接テキストファイルを作成する際などによく使われました。

  • PRN(プリンター)
    役割: パラレルポートに接続されたプリンターへの出力。
    用途: テキストを印刷する際の出力先として指定されました。

  • AUX(補助デバイス)
    役割: シリアルポートに接続された通信機器などとの入出力。
    用途: モデムや外部のシリアル端末とデータをやり取りする際に使用されました。

  • NUL(ヌルデバイス)
    役割: データをどこにも出力せずに破棄する、または空の入力を返す仮想デバイス(UNIXの /dev/null 相当)。
    用途: コマンドの画面出力を非表示にしたい時(例:COMMAND > NUL)の受け皿として使われました。

Ver.2での進化:デバイスの拡張と「ANSI.SYS」

Ver.2になると、CONFIG.SYS に DEVICE= という記述を行うことで、新しいデバイス(デバイスドライバー)を後から追加できるようになりました。さらに、複数の同じデバイスを扱うために、最後に数字を加えたデバイス名が利用できるように拡張されます。

  • COM1 / COM2(シリアルポート)

  • LPT1 / LPT2(パラレルポート)

この時、従来の PRNはLPT1の別名、AUXもCOM1の別名として扱われ、どちらの名前からでも、自動的にデバイスへリダイレクトされて使えるようになっていました。

また、この仕組みを利用して ANSI.SYS といったデバイスをインストールすることで、CON(コンソール)を置き換え、画面上でエスケープシーケンス(文字色の変更やカーソル移動など)を利用できるようにする、といった使い方も登場しました。

「コロン(:)」をなくしたMS-DOSと、現代に続く「CON」の呪い

実は他にも CLOCK$ という、MS-DOSというOS自体が現在時刻を知るため(あるいは時計を設定するため)に内部で利用するデバイスも存在していました。これはシェルから直接使えるものではなく(DATEコマンドなどを経由する)、あくまで内部的なデバイス名です。

面白いのは、MS-DOSがデバイス名に「CP/M」に準じた名前を採用したのにもかかわらず、末尾のコロン(:)を廃止してしまった点です。
おそらく「デバイスもファイルと同じように扱えるべきだ」というUnixライクな思想からの主張だったのでしょうが、これが原因で「デバイス名と同じ名前のファイルが作れない」という問題が発生してしまいました。

例えば、今でもWindowsで "CON" という名前のフォルダーやファイルを作ろうとするとエラーになりますよね。そんな制約をすっかり忘れている現代のユーザーが、たまに直面してビックリすることがあります(※特殊な表記を使うことで回避は可能です)。

ちなみに、先ほどの内部デバイスがわざわざ CLOCK$ となっているのは、当時すでに "CLOCK" というファイル名がよく使われていたからだと言われています。ここだけ末尾に $ をつけて衝突を避けているところを見ると、当時の開発者もこの問題をハッキリと認識していたはずなんですけどね。

XENIXの思想と「ファイルハンドル」の登場

Ver.2以降では、Unix系OSである「XENIX」の考え方が導入されました。
これにより、これら標準デバイスはプログラム実行時にあらかじめ「ファイルハンドル」が割り当てられるようになり、面倒な「オープン」という操作なしで、いきなり読み書きが出来るようになっています。

  • 0:標準入力(stdin)/ CON

  • 1:標準出力(stdout)/ CON

  • 2:標準エラー出力(stderr)/ CON

  • 3:標準補助装置(stdaux)/ AUX

  • 4:標準プリンタ(stdprn)/ PRN

これらのハンドル(※初期の COMMAND.COM でリダイレクト指定できたのは stdin と stdout だけですが)は、プログラム起動時にリダイレクトが指定されていれば、自動的に指定されたファイルやデバイスに接続された状態になります。

COOKED(整形)かRAW(生)か? 入出力のバッファリング問題

入出力の「あるある」なテーマが、バッファリングの有無です。

  • COOKEDモード(デフォルト):DOSによってデータがバッファリング(一時変更や蓄積)されます。

  • RAWモード:IOCTL(I/Oコントロール)を使って切り替えるモード。DOSはバッファリングをせず、直接プログラムにデータを渡します。

DOSを挟まないRAWモードにすると表面的なパフォーマンスが上がりますが、引き換えに CTRL-C での強制終了のハンドリングや、キー入力時のエコーバック(画面への文字表示)などに影響が出るため、一長一短でした。

なぜ当時のプログラマーは「ROM BIOS」を乱用したのか?

キーボードや画面といったデバイスに対して、汎用的な処理を行うDOSの機能だけでは、どうしても「かゆいところに手が届かない」ケースが多々ありました。

  • キーボードの「NUM LOCK」の状態を取得したい

  • 「CTRLキー」が押された瞬間をリアルタイムにキャッチしたい

  • 画面の文字を装飾したり、正確なカーソル位置を取得したい

このような場合、多くのプログラムはDOSの標準機能を通さず、ハードウェアに直結した「ROM BIOS」の機能を直接呼び出していました。いわゆる「PC/AT互換機」の市場であれば、BIOSに関しても互換性が保たれていたため、みんな躊躇なくBIOSを直接叩いていたきらいがあります。

しかし、これが原因で問題が起こります。MS-DOSという「機種に依存しないプラットフォーム」を目指していたはずなのに、例えば日本の国民機だった「PC-9801」などで海外のソフトを動かすには、これらBIOS呼び出しを書き換える「移植作業」が必須になってしまったのです。そのため、MS-DOS時代は大部分のプログラムを、互換機以外でそのまま動かすことは出来ませんでした。

もちろん、DOS側にも IOCTL という仕組みでデバイス固有の制御を行う仕掛けはあったのですが、これだけですべての機能をカバーするには力不足。結局、通信パラメータの設定や、プリンターの詳細な状態を知るためにも、BIOS呼び出しが乱用されていたのが当時の実態でした。

NotebookLMによるインフォグラフィック

NotebookLMによるスライド資料

NotebookLMによるまとめ記事

ショート動画

NotebookLMによる解説動画

NotebookLMによる音声解説

ヘッダ画像は、Gemini に描いてもらいました。

#MSDOS #OS #Windows #レトロPC #PC98 #ITの歴史 #技術の歴史 #プログラミング #キャラクタデバイス #エンジニア


いいなと思ったら応援しよう!

kzn 頂いたチップは記事を書くための資料を揃えるために使わせていただきます!