まずは分かりやすいプロセスとスレッドから。
Windows や Linux などの汎用 OS 上のアプリケーションは一般にプロセスとして動作している。プロセスはプログラムの実行単位である。プロセスは1つ以上のスレッドと、ファイル、ヒープメモリなどのリソースで構成される。一方、スレッドは CPU 利用の単位である。スレッドはそれぞれが専用のスタックと CPU レジスタのコピーを保持するが、ファイルやヒープメモリは同一プロセス内の全てのスレッドで共有する。
スレッドのさらにサブセットがファイバである。スレッドとの違いは切り替え動作にありファイバのほうが軽いというメリットがある。プロセス、スレッド、ファイバの関係はこちらの説明が分かりやすかった。
プロセスはプログラム実行のための固有のメモリ空間を持っており、最も独立性の高い実行単位である反面、起動や切り替えに時間がかかるという特性を持っています。これに対してスレッドはプロセスのサブセットとして動作し、実行に必要なメモリ空間を複数のスレッドで共有。このため起動や切り替えのオーバーヘッドが小さく、“Lightweight Process(軽量プロセス)”とも呼ばれています。ファイバとはスレッドをさらに軽量化したもの。スレッドとの違いは切り替え時の動作にあります。スレッドの切り替えにはユーザーモードからカーネルモードへの移行が必要なのに対し、ファイバではユーザーモードのまま他のファイバへ処理を切り替えることができるのです。このためスレッドよりもオーバーヘッドが小さく、マルチプロセッサ環境ではプロセッサ毎に同期化スケジュールが作成されるため、プロセッサ間の同期処理で発生するスピンロックも回避できます。
一方、タスクという言葉は曖昧である。(1) プロセスと同じ意味で使われる場合、(2) スレッドのことを指す場合、あるいは (3) プロセスよりも大きな集合として使われる場合もある。
- ファイバ ⊂ スレッド ⊂ プロセス (= タスク)
- ファイバ ⊂ スレッド (= タスク) ⊂ プロセス
- ファイバ ⊂ スレッド ⊂ プロセス ⊂ タスク
ちなみに Windows では個々のアプリケーションはプロセスとして動作するが、それを確認するツールの名前はタスクマネージャーと呼ばれており非常に紛らわしい。Linux の世界でもタスクという言葉は曖昧なようだ。
Linux のカーネル開発者は「スレッド」や「プロセス」というかわりに、「タスク」という言葉をよく使う点に注意してください。しかし、対外的なドキュメントには、プロセスという言葉を使います。
また Wikipedia にはこう書かれている。
1つのタスクは、1つ以上のプロセスから構成され、1つのプロセスは、1つ以上のスレッドから構成される。集合で表すと、スレッド ∈ プロセス ∈ タスクというようになる。しかし、この関係は環境によって異なる。例えば、リアルタイムOSでは、タスク≒スレッド、スレッド ∈ プロセス、である。しかし、タスクとプロセスの間に要素関係はない。
組み込み系ではタスク=スレッドと考えて問題ないと思う。実は私が組み込み系の仕事を始めたときこの部分がしっくり来なかった。タスク=スレッドというのならばプロセスに相当するものは何?という問いに答えられなかったからだ。組み込み系ではシステム全体が1つのプロセスであり、それに含まれるスレッドに相当するものがタスクと考えるとしっくりくる。また、最近読んだ本にはこのような記述があったので引用しておく。
基本的には、コンテキストが消滅するときに道連れにするリソースがある場合にはプロセス、道連れにしない場合にはスレッドと呼ばれると考えて間違いないでしょう。
μITRON準拠TOPPERSの実践活用―製品開発にも学習教材にも使えるフリーのOSプラットホーム (TECH I Embedded Software)
ここでいうコンテキストとは ITRON 4.0 仕様における用語で、プログラムの実行環境、具体的にはタスクの切り替えに必要な CPU のレジスタなどを指している言葉。
ジョブという言葉はプロセスと似ているが、特にユーザーから見た処理の単位を表す。例えば unix の jobs コマンドで表示されるジョブはシェルが管理する仕事の単位となっている。こちらの説明が分かりやすい。
「ジョブ」とは、プロセスと似た概念で、現在実行中のプログラムのことを指す。ジョブとプロセスの違いは、
% ls | more
のようなパイプを使った場合に現れる。ls と more はそれぞれ別のプロセスだが、ls | more はひとつのジョブである。上記の場合、ls を実行したまま more を止める、というような操作は (操作している人にとっては) あまり意味がない。操作している人の立場から見て、複数のプロセスをグループ化したものがジョブである。
2007-03-19 スレッドとファイバの違いの説明を追加。
スレッドとファイバーの決定的な相違は、スレッドの実行はオペレーティングシステムのスケジューラーに制御されますが、ファイバーの実行はアプリケーションが自ら制御できる点です。オペレーティングシステムは、ファイバーの実行に CPU 時間の割り当て(つまり限定)を行ないません。
2008-07-10 Linux におけるタスクという用語の説明を追加。
Linux では、特にスケジューラーの議論において、プロセスとスレッドを総称して「タスク」と呼ぶことがあります。これは、Linux のスレッドがアドレス空間を共有するプロセスとして実装されているので、スケジューリングの点で区別がないからです。