『プロセス』と『スレッド』と『ファイバ』
Windows や Linux などの汎用 OS 上のアプリケーションは、一般にプロセスとして動作しています。
プロセスは、プログラムの実行単位です。
プロセスは、1つ以上のスレッドと、ファイル、ヒープメモリなどのリソースで構成されています。
スレッドは、 CPU 利用の単位です。
スレッドは、それぞれが専用のスタックと CPU レジスタのコピーを保持しますが、ファイルやヒープメモリは同一プロセス内の全てのスレッドで共有します。
⇩ ヒープメモリ(ヒープ領域)とスタックについては下記サイトへ
・学校では教えてくれないこと | 技術コラム集(組み込みの門) | ユークエスト
⇩ レジスタについては下記サイトへ
・アセンブラで学ぶコンピュータ基礎のキソ-第1回 「レジスタ」を知るとCPUの細かな処理が見えてくる : ITpro
⇩ プロセスとスレッドの違いについては下記サイトへ
・Wake up! Good night*-プロセスとスレッドの違い
スレッドのさらにサブセットがファイバです。
サブセット 【 subset 】
サブセットとは、一部分、部分集合、下位集合などの意味を持つ意味の英単語。
ある集団全体を構成する要素の一部を取り出して構成した小集団のこと。
対義語はフルセット(full set)。
ITの分野では、仕様や規格、ソフトウェアなどの機能についてよく用いられる用語で、本来備えている要素の一部を省略・削除した簡易版・限定版という意味で用いられることが多い。
スレッドとの違いは切り替え動作にあり、ファイバのほうが軽いというメリットがあります。
⇩ プロセス、スレッド、ファイバの関係
プロセスはプログラム実行のための固有のメモリ空間を持っており、最も独立性の高い実行単位である反面、起動や切り替えに時間がかかるという特性を持っています。
これに対してスレッドはプロセスのサブセットとして動作し、実行に必要なメモリ空間を複数のスレッドで共有。
このため起動や切り替えのオーバーヘッドが小さく、“Lightweight Process(軽量プロセス)”とも呼ばれています。
ファイバとはスレッドをさらに軽量化したもの。
スレッドとの違いは切り替え時の動作にあります。
スレッドの切り替えにはユーザーモードからカーネルモードへの移行が必要なのに対し、ファイバではユーザーモードのまま他のファイバへ処理を切り替えることができるのです。
このためスレッドよりもオーバーヘッドが小さく、マルチプロセッサ環境ではプロセッサ毎に同期化スケジュールが作成されるため、プロセッサ間の同期処理で発生するスピンロックも回避できます。
⇩ スレッドとファイバの違い
スレッドとファイバーの決定的な相違は、
スレッドの実行はオペレーティングシステムのスケジューラーに制御されますが、ファイバーの実行はアプリケーションが自ら制御できる点です。
オペレーティングシステムは、ファイバーの実行に CPU 時間の割り当て(つまり限定)を行ないません。
タスクの曖昧さ
- プロセスと同じ意味で使われる場合
- スレッドのことを指す場合
- プロセスよりも大きな集合として使われる場合
Windows では個々のアプリケーションはプロセスとして動作しますが、それを確認するツールの名前はタスクマネージャーと呼ばれており非常に紛らわしいです。
『ジョブ』と『プロセス』
⇩ ジョブとプロセスの関係
「ジョブ」とは、プロセスと似た概念で、現在実行中のプログラムのことを指す。ジョブとプロセスの違いは、
% ls | more
のようなパイプを使った場合に現れる。
ls と more はそれぞれ別のプロセスだが、ls | more はひとつのジョブである。
上記の場合、ls を実行したまま more を止める、というような操作は (操作している人にとっては) あまり意味がない。
操作している人の立場から見て、複数のプロセスをグループ化したものがジョブである。
UNIXの部屋 コマンド検索:jobs (*BSD/Linux)
『マルチスレッド』
一つのメモリ空間を共有します。
グローバル変数は共有になります。
2つのスレッドの情報交換はグローバル変数を使ってできます。
『マルチプロセス』
メモリ空間が別々に確保されるので、グローバル変数で情報の受け渡しはできません。
情報の受け渡しはプロセス間通信とか共有メモリとかを使います。
Apacheのプロセスの挙動
Apacheはプロセスの挙動として
- prefork
- worker
- event
3のつの方式を持っています。
prefork
preforkは『スレッドを使わず、先行して fork を行なうWebサーバ』です。
Apacheは伝統的に親プロセスを1つ持ち、クライアントからリクエストが来ると自分自身をコピーして子プロセスを起動します(これをforkという)。
実際の通信は子プロセスが受け持ちます。
そのため、通信している数だけ子プロセスが起動することになります。
この時、クライアントからリクエストを受けたあとでforkすると、fork完了までに待ち時間が出来て通信のパフォーマンスが遅くなります。
そのため、あらかじめいくつかの子プロセスをforkしておき、forkの待ち時間をなくす方式をとっています。
この方式が『prefork』です。
すなわち“pre(=前もって・先行して)”forkしておく、という意味です。
preforkのメリットは、forkされた子プロセス1つ1つが対応する通信を受け持つため、ある子プロセスが何らかの原因でフリーズしたとしても、他の子プロセスには影響を及ぼすことが無く通信を継続できます。
このため安定した通信を行うことが出来ます。
一方、クライアントが多くなればなるほど子プロセスの数も増えるため、使用メモリ量やCPU負荷が比例的に増大していきます。
preforkで多数のクライアントをさばくには、それに応じた大量のメモリと高速なCPUが必要となります。
worker
workerは『マルチスレッドとマルチプロセスのハイブリッド型サーバ』です。
Apacheの子プロセス1つ1つがマルチスレッドで動作し、スレッド1つが1つのクライアントを受け持つ方式です。
すなわち、1つのプロセスがマルチスレッドを利用して複数の通信の面倒を見ます。
この点で1つのプロセスが1つの通信をみるpreforkとは異なります。
また多くの子プロセスを起動せずに済むため、メモリの使用量も減らすことが出来ます。
event
eventはworkerの一種でマルチスレッドで動作します。
workerとの違いはKeep-Alive(持続的接続)の処理方法です。
workerやpreforkは、Keep-Aliveの持続性を保つために一度利用したスレッド・プロセスをそのまま待機させています。
しかしクライアントからの接続が持続的に行われる可能性は保証されているわけではないため、待機していること自体が無駄になる可能性もあります。
そこで、Keep-Aliveの処理を別のスレッドに割り振って通信を処理します。
この方式は長らく実験的サポートであったが、2.4.1にて正式に採用されました。
キープアライブ 【 keep alive 】 キープアライブパケット
キープアライブとは、ネットワーク上で、接続が有効であることを確認するために定期的に行われる通信。
ネットワークで接続されたコンピュータやネットワーク機器は、通信相手から長時間通信がないときに、用がないから黙っているのか、ダウンしてしまったのか確認する術がない。
仮想的に通信路(セッション)を形成してデータの送受信を行うコネクション型の通信の場合、通信終了の合図がないまま相手が異常終了してしまうと、永久にセッションを閉じることができなくなってしまう。
このため、多くのプロトコルやアプリケーションでは、用がないときでも一定時間ごとに「生きている」(alive)ことを相手に伝えるための信号を送るように設計されている。
これがキープアライブ機能である。
無通信状態が一定時間以上続いてもキープアライブ信号が届かない場合には、接続を切る。
キープアライブを行うための信号のことを「ハートビート」と呼ぶことがある。
パケット通信では、キープアライブ用に送受信されるパケットを「キープアライブパケット」という。
今回はこのへんで。