PCで複数のアプリケーションを同時利用することは当たり前になった。PowerPointやWordで資料を作りながら、Webブラウザで検索し、作業合間でチャットに応答しても驚く人はいないだろう。しかし、ここに至るまでにはさまざまな課題があった。今回は、複数のアプリケーションを同時に実行すること、つまり「マルチタスク」の話である。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
初期のコンピュータは、同時に複数の処理ができなかった。企業向けのコンピュータ(今でいうサーバ)では1960年代から「マルチタスク」の研究が始まり、1970年代には一般化していた。しかし、パーソナルコンピュータ(PC)で原始的なマルチタスクが実行可能になったのは1980年代からである。
今回は、PCのマルチタスクで特に大きな影響を与えたシステムを紹介する。
「複数のプログラムを同時に実行したい」という要求は、人としてごく自然なものである。他のプログラムの処理中に別の処理をしたい場合は多い。1981年の「MS-DOS 2.0」では「TSR」(Terminate and Stay Resident)という仕組みが用意され、原始的なマルチタスクが可能になった。TSRを使ったプログラムもTSRと呼ぶ。
MS-DOSの標準的な構成では、例えばワードプロセッサで文書を作成しているときに、スケジュール帳を起動したくなったら、以下のような作業が必要になる。
TSRを使うことで、こうした煩わしさを解消できた。米国では「Sidekick」というTSRアプリケーションが広く使われた(筆者の記憶では日本語版は存在しないため、使っていた人は少ないだろう。筆者も実物を見たことはない)。
Sidekickは「PIM」(Personal Information Manager)と総称されるアプリケーションの一種で、スケジュール管理やアドレス帳、ToDoリスト、メモ帳などを提供する。Sidekickを実行しても画面は表示されないし、他のアプリケーションも問題なく利用できる。しかし、特定のキー操作(既定では[Ctrl]+[Alt]キーの同時押し)で即座にSidekick画面が表示され、スケジュール帳やアドレス帳を使用できる。Sidekickの操作に実行中の他のアプリケーションは影響を受けず、終了する必要もない。つまり、以下のような動作になる(図1)。
TSRはバックグラウンドで実行するプログラムであり、特定のキー操作やタイマーによって呼び出すのが一般的だ。
TSRの原理は以下の通りである。
TSRはホットキーで呼び出す他、タイマーで定期的に実行するなど、さまざまな利用方法があった。シングルタスクのMS-DOSを使う上では便利な機能だったが、起動後は画面を表示していなくてもメモリを確保し続けるという欠点があった。また、MS-DOSはメモリ保護機能が不完全なため、TSRの不具合で他のアプリケーションのメモリを侵害する可能性もあった。メモリ侵害が発生すると、結果としてアプリケーションが誤動作を起こす。
このような欠点はあるものの、MS-DOS 2.0では主たるアプリケーションと割り込んで実行する補助アプリケーション(TSR)の併用が可能になった。
しかし、TSRはTSRとして最初からプログラムする必要があり、一般的には「マルチタスク」の部類には含めない。TSRとして作成されていないアプリケーション、例えば手持ちのワードプロセッサと表計算ソフトウェアを同時に実行することはできないからだ。
1984年に「Apple Macintosh」が発売された。その前年にはウィンドウシステムを標準搭載した「Apple Lisa」が登場していたが、価格は1万ドル(当時の為替レートで約240万円)と、そう簡単に買える金額ではなかった。その点、Macintoshの価格は約2500ドル、日本では約70万円だった。高いことは高いがLisaよりはだいぶ安かった。
さて、Macintoshはオーバーラップ可能な(重ね合わせ可能な)ウィンドウを持つので、当然マルチタスクを実現したと思っている人も多いが、そうではなかった。
最初のMacintoshは、電卓や時計など「デスクアクセサリ」(DA)と呼ばれる幾つかのアプリケーションを除いてマルチタスクに全く対応していなかった。
その後、1985年に「Switcher」というシステムが追加され、前回紹介したような「アプリケーションの切り替え」ができるようになった。ただし、画面を使っていないアプリケーション(デスクトップに出ていないアプリケーション)の動作は停止した。
その当時、Macintosh開発チームは「ユーザーは同時に複数の作業をするわけではないから、複数のプログラムを同時に実行する必要もない」と言った。もっとも、複雑な計算が終わるまでの待ち時間に別のことをすることはあったので、この発言はポジショントークだった可能性が高い。
本格的なマルチタスクを実装するには、単純にCPU能力やメモリ容量が足りなかったのだろう。初期のMacintoshの搭載メモリは128KB(MBではない)、拡張メモリスロットはなかった。現在のPCは8GB程度のメモリを搭載している。初代Macintoshの6万倍以上である。
Macintoshにマルチタスク(後述する「協調型マルチタスク」)が導入されたのは1987年の「MultiFinder」からとされている(この頃はメモリ容量が1MB程度になっていた)。
ちなみにMacintoshのOSには当初名前がなく、単に「System」と呼ばれていた。ハードウェアとセットで提供していたため、バージョン以外の区別は必要なかったのだろう。Macintosh互換機が登場してからは、通称として「Mac OS」が使われており、後に正式名称になった。現在は「macOS」が正式名称となっている。
Windowsは当初からマルチタスクを実現していたが、「Windows 1.0」から「Windows 3.1」までは「ノンプリエンプティブ」と呼ばれるものだった。「ノン」という否定語が好ましくないということで、Microsoftは「協調型(cooperative)マルチタスク」という言葉を好んで使っていた。「ノンプリエンプティブ」を説明するには「プリエンプティブ」について理解する必要があるので、ここでは「協調型」で統一する。
マルチタスクは、実際に複数のアプリケーションを完全に同時実行するわけではない。数十ミリ秒程度の短い時間でアプリケーションを切り替えることで、人間に同時実行しているように見せかける仕組みである。
協調型マルチタスクに対応したアプリケーションは、マウスの入力待ちなどのタイミングで自らCPUの利用権を放棄し、別のアプリケーション(正確にはアプリケーション内部の動作単位である「タスク」)に譲る。実行待ちのタスクがない場合は、あらためてCPU利用権を獲得して動作を継続する(図2)。
CPU利用権の放棄はアプリケーションに任されているため(これが「協調的」の意味)、アプリケーションのバグなどでCPUを放棄しない場合(つまり協調的でない場合)は、タスクが切り替えられない、いわゆる「ハング」という状態になる。Windows 3.1では[Ctrl]+[Alt]+[Del]キーを押すことで「協調的でない」アプリケーションを強制停止する機能があったが、常に動作するとは限らなかったように思う。
協調型マルチタスクでは、連続して長時間CPUを使い続けることは許されない。もしそうなったら、他のアプリケーションが一切動かなくなるからだ。そこで、長時間かかることが予想される場合は、他のタスクがCPUを要求していないかどうかをチェックする機能を所々に組み込む必要があった。これを「yield(譲る)」と呼ぶ。
協調型マルチタスクは、タスク切り替えのタイミングをアプリケーションが自発的に決めるため、OSの負担が少ない。そのため、初期のPC用OSでは広く使われた。
例えば、前述の通り、MacintoshはMultiFinderでマルチタスクを実現しているが、これは協調型マルチタスクである。Macintoshが後述するプリエンプティブなマルチタスクに移行するのは、UNIXベースの「Mac OS X(テン)」(現在のmacOS)からであり、一般提供されたのは2001年である。その他、サーバ専用OSとして広く使われた「NetWare」も協調型マルチタスクだった。
協調型マルチタスクは、OSの負担が軽い。つまり、OSに必要なCPUやメモリなどのリソースも少なくて済むため、アプリケーションにより多くのリソースを与えることができる。しかし、前述の通り、アプリケーションがCPUを使い続けてしまうとシステム全体が停止してしまうという大きな欠点がある。世界中の全てのアプリケーションが正しく動作することを前提にはできないので、PC用アプリケーションが増えるに従って、協調型マルチタスクの欠点が問題になってきた。
そこで、Microsoftが新しく設計したOSが「Windows NT」(1993年)である。Windows NTでは後述する「プリエンプティブなマルチタスク」が実装され、これにより協調型マルチタスクの欠点が解消された。
また、Windows 3.1の後継として登場した「Windows 95」(1995年)は、Windows NTの技術を取り入れる形でプリエンプティブなマルチタスクが実装された。ただし、Windows 3.1互換プログラムは協調型マルチタスクで動作し、プリエンプティブなマルチタスクが利用されるのはWindows 95用に作成されたアプリケーションのみである。
協調型マルチタスクの欠点を解決するために登場したのが「プリエンプティブなマルチタスク」で、1993年にWindows NTとともに登場し、現在のWindowsまで採用されている(図3)。
ただし、歴史的にはプリエンプティブなマルチタスクの方が早く登場した。協調型マルチタスクでは、何らかのきっかけで「待ち状態」を発生させる必要がある。GUI(グラフィカルユーザーインタフェース)ではボタンを押すのを待ったり、画面描画を待ったりなど、多くのタイミングで待ちが発生する。ほとんどの場合、先に紹介した「yield」といったテクニックを使う必要はない。特別な工夫をしなくても、大抵の場合は自然に「待ち状態」が発生し、複数のアプリケーションを問題なく利用できる。
しかし、キャラクタベースの(GUIでない)アプリケーションが待ち状態に移行することはめったにない。その上、初期のコンピュータはそもそも対話的な操作をしなかったため、ユーザーの入力待ちすら存在しない。せいぜいファイルの入出力くらいである。そのようなアプリケーションで協調型マルチタスクを実現するのは難しい、というより当時は「自分から待ち状態に入る」という動作を思い付かなかったのではないだろうか。
伝統的なマルチタスクは、単位時間ごとにCPUの利用権を強制的に奪い、他のタスクに割り当てる。このときの単位時間を「クォンタム」と呼ぶ。CPUを奪われたタスクは、後で続きを実行するために動作状態を保存しておく必要がある。このような状態の保存と復元を「タスクスイッチ(タスク切り替え)」と呼ぶ。タスクスイッチは比較的重い(CPUの負担が大きい)作業だが、アプリケーションプログラマーはタスク切り替えのことを一切考える必要がなくなる。ひたすら計算していても、クォンタム時間がくれば自動的に他のタスクを実行してくれるからだ。
「Windows 11」のクォンタムは既定で約20〜30ミリ秒、「Windows Server」の場合は120ミリ秒程度になる(ハードウェアに依存)。タスクスイッチはそれだけでCPU時間を消費するため、クォンタムを短くすると切り替え回数が増え、結果としてOSの負荷が上がり、最終的にアプリケーションに割り当てられるCPU時間が少なくなる。そのため、サーバではクォンタムを長く設定している。しかし、クォンタムが長いとタスクが切り替わるまでの最小時間が長くなるため、応答性は下がってしまう。そのため、クライアントOSではクォンタムを短く設定して、素早く応答できるようにしている。
プリエンプティブなマルチタスクには、クォンタムの他にも優先順位の概念がある。本来の「プリエンプティブ(preemptive)」はこちらの意味である。辞書を引くと「先取権」とか「先制攻撃」といった訳が並んでいる。「優先的に権利を得る」「相手より先に行動する」くらいの意味である。
同じ優先度のタスクは、先に説明したクォンタム時間単位で順序よく公平に切り替わる(これを「ラウンドロビン」と呼ぶ)。しかし、優先順位の高いタスクは常に優先的に実行される。このとき、たとえクォンタム時間を使い切っていなくても、クォンタムの途中で強制的に切り替わる。
Windows NTではプリエンプティブなマルチタスクをカスタマイズするための機能があり、現在のWindows 11やWindows Serverでも使用できる(図4)。具体的には以下の2つのどちらかを選択することで、クォンタムと優先順位の両方を同時に変更できる。
実際のWindowsでは、あまりに長い間CPUが割り当てられないタスクの優先度を一時的に上げるなど、優先順位を細かく調整することで「永久に動かないタスク」が発生しないように考慮されている。そのため、特定のアプリケーションのトラブルで他のアプリケーションまで停止するようなことは起きない。
一方、協調型マルチタスクでは、全てのアプリケーションが適切な振る舞いをしていれば効率よく動作するが、作りが悪いと他のアプリケーションが一切動作しなくなってしまう。CPU性能が向上した現在では、協調型マルチタスクを使う意味はなくなったと言える。
これは余談になる。プリエンプティブなマルチタスクが実装されたのはWindows NTからだが、実は「Windows 3.0」でも部分的にプリエンプティブなマルチタスクが実装されていた。それが「MS-DOSウィンドウ」、通称「DOS窓」である。
Windows 3.0の「エンハンスドモード」(日本語版で一般的だったモード)では、MS-DOSコマンドを実行するときに2つのモードがあった。
ウィンドウモードでは複数のウィンドウ(DOS窓)を開くことで、複数のMS-DOSコマンドを実行できるが、MS-DOSはもちろんマルチタスクには対応していない。つまり、実行中はCPUを占有する。DOS窓を2つ開いた場合、2つのプログラムがどちらもCPUを占有しようとするが、協調型マルチタスクでは一方しか動作しないはずである。これでは使い物にならないので、DOS窓に限ってはクォンタムの概念を使って、複数のDOS窓を定期的に切り替えて実行する。
DOS窓の実行はクォンタムに基づくラウンドロビンで、優先順位の考え方はないが、強制的な切り替えができるということで、プリエンプティブなマルチタスクに分類されている。
「ラウンドロビン」(Round-Robin)は、コマドリ(Robin)がクルクル回っている様子から生まれた言葉、ではない。「ロビン」はフランス語の「リュバン」(ruban)が英語的に訛(なま)った言葉で、日本語の「リボン」である。
17〜18世紀、フランスの農民が国王に直訴した場合、直訴状に記載された名前の先頭から数名を処刑したという。そこで、誰が先頭か分からないようにリボン状に署名したそうだ。このことから、「対等な関係の仲間が協力して実行する」という意味になった。日本でも同様の習慣があり、こちらは「傘連判状」と呼ばれる。
現在は協調型マルチタスクが使われることはほとんどなくなったため、対応するプリエンプティブなマルチタスクについても知らない方が増えている。知らなくても特に問題はないのだが、少しでもOSの内部に興味を持っていただければ幸いである。
トレノケート株式会社(旧グローバル ナレッジ ネットワーク株式会社)で、マイクロソフト認定トレーナーとしてMicrosoft AzureやWindows ServerなどのIT技術者向けトレーニングを担当。Windows Serverの全てのバージョンを経験。近著に『徹底攻略 Microsoft Azure Fundamentals教科書[AZ-900]対応 第2版』(インプレス)、『ストーリーで学ぶWindows Server ひとり情シスのためのITシステム構築入門』(日経BP社)がある。好きなサービスはActive Directoryドメインサービス、推しているアイドルは皆本しいね(「君のメインヒロイン」所属)。
Copyright © ITmedia, Inc. All Rights Reserved.