コンピュータサイエンスにおいて、メッセージパッシングとは、コンピュータ上で動作(すなわちプログラムの実行)を呼び出すための手法です。呼び出し元のプログラムは、プロセス(アクターまたはオブジェクト)にメッセージを送信し、そのプロセスとそのサポートインフラストラクチャに依存して、適切なコードを選択して実行します。メッセージパッシングは、プロセス、サブルーチン、または関数を名前で直接呼び出す従来のプログラミングとは異なります。メッセージパッシングは、並行処理やオブジェクト指向プログラミングのいくつかのモデルにおいて重要な役割を果たします。
メッセージパッシングは、現代のコンピュータソフトウェアにおいて広く用いられています。これは、プログラムを構成するオブジェクト同士が連携するための手段として、また、異なるコンピュータ上で動作するオブジェクトやシステム(例えばインターネット)が相互作用するための手段として利用されます。メッセージパッシングは、チャネルを含む様々なメカニズムによって実装されます。
メッセージパッシングは、コンピュータ上で動作(すなわちプログラムの実行)を呼び出すための技術です。従来のプログラム名による呼び出しとは異なり、メッセージパッシングではオブジェクトモデルを用いて、一般的な機能と具体的な実装を区別します。呼び出し元のプログラムはメッセージを送信し、オブジェクトが適切なコードを選択して実行します。中間層を使用する理由は、主にカプセル化と分散という2つのカテゴリに分類されます。
メッセージパッシングは、並行システムと分散システムの両方において、プロセス、スレッド、オブジェクト、またはノード間の通信に使用されるコア技術です。これにより、ソフトウェアコンポーネントはメモリを共有することなく情報を交換でき、多くの場合、通信チャネル、バッファ、またはミドルウェアを使用して送信者と受信者の間でメッセージを転送します。一部のモデルでは、メッセージパッシングは同期的に実装できます。同期的に実装すると送信者は応答を待ちます。非同期的に実装するとメッセージは後で処理するためにキューに格納されます。[ 1 ]
カプセル化とは、ソフトウェアオブジェクトが、他のオブジェクトのサービスがどのような実装で行われているかを知らなくても、あるいは気にしなくても、それらのサービスを呼び出すことができるようにするという考え方です。カプセル化によって、コーディングロジックの量を減らし、システムの保守性を向上させることができます。例えば、どのサブルーチンや関数を呼び出すかを決定するIF-THEN文を使う代わりに、開発者はオブジェクトにメッセージを送信するだけで、オブジェクトはメッセージの種類に基づいて適切なコードを選択します。
この技術がどのように活用できるかを示す最初の例の一つは、コンピュータグラフィックスの分野でした。グラフィックオブジェクトの操作には、さまざまな複雑な要素が伴います。例えば、囲まれた図形の面積を計算するための適切な数式は、その図形が三角形、長方形、楕円、円のいずれであるかによって異なります。従来のコンピュータプログラミングでは、図形の種類をテストし、適切なコードを呼び出す長いIF-THEN文が必要になります。オブジェクト指向でこれを処理する方法は、やShapeなどのサブクラス(さらに や などのサブクラスを持つ)を持つ というクラスを定義し、任意のオブジェクトに面積を計算するように要求するメッセージを送信することです。すると、各オブジェクトは、その種類のオブジェクトに適した数式を使用して、サブクラスの メソッドを呼び出します。[ 2 ]RectangleEllipseSquareCircleShapeShape
分散メッセージングは、異なる場所や異なる時間に異なるコンピュータ上で動作するサブシステムで構成されるシステムを構築するための共通サービスを提供するアーキテクチャ層を開発者に提供します。分散オブジェクトがメッセージを送信する際、メッセージング層は次のような問題を処理できます。
同期メッセージパッシングは、同時に実行されているオブジェクト間で行われます。JavaやSmalltalkなどのオブジェクト指向プログラミング言語で使用されています。
同期メッセージングは同期関数呼び出しに似ています。関数呼び出し元が関数の完了を待つのと同様に、送信プロセスは受信プロセスがメッセージを受け入れるまで待ちます。[ 4 ]このため、同期通信は一部のアプリケーションでは実用的ではない場合があります。たとえば、大規模な分散システムでは、実用的に十分なパフォーマンスが得られない可能性があります。このような大規模な分散システムは、一部のサブシステムがメンテナンスなどで停止している間も動作する必要がある場合があります。
忙しいオフィスを想像してみてください。100台のデスクトップコンピュータがあり、それらはすべて同期メッセージパッシングのみを使用して互いに電子メールを送受信しています。従業員の1人がコンピュータの電源を切ると、その従業員がコンピュータの電源を再び入れて1通の電子メールを処理するまで、他の99台のコンピュータがフリーズしてしまう可能性があります。
メッセージパッシングシステムは、送信および受信操作が実行中のプロセスとどのように相互作用するかに基づいて、大まかに分類できます。同期メッセージパッシングでは、送信プロセスは受信側がメッセージを受け入れるまでブロックし、厳密な連携が確保されます。非同期モデルでは、送信側はメッセージを送信した後も実行を継続し、メッセージは通常、受信プロセスが取得するまでキューまたはバッファに格納されます。[ 5 ]
非同期メッセージパッシングでは、要求オブジェクトがメッセージを送信したときに、受信オブジェクトがダウンしていたり、ビジー状態だったりする可能性があります。関数呼び出しのアナロジーを続けると、呼び出された関数が完了するのを待たずにすぐに戻る関数呼び出しのようなものです。メッセージはキューに送信され、受信プロセスが要求するまでそこに格納されます。受信プロセスはメッセージを処理し、結果をキューに送信して、元のプロセス(または指定された次のプロセス)が取得できるようにします。[ 6 ]
非同期メッセージングでは、同時に実行されない可能性のあるシステム間でデータを保存および再送信するための追加機能が必要となり、通常は中間レベルのソフトウェア(ミドルウェアと呼ばれることが多い)によって処理されます。一般的なタイプとしては、メッセージ指向ミドルウェア(MOM)があります。
非同期通信に必要なバッファがいっぱいになると問題が発生することがあります。送信者をブロックするか、今後のメッセージを破棄するかを決定する必要があります。送信者がブロックされるとデッドロックが発生する可能性があります。メッセージが破棄されると、通信の信頼性が失われます。
同期通信は、シンクロナイザを使用することで非同期通信の上に構築できます。たとえば、α-シンクロナイザは、送信側が常に受信側からの確認応答メッセージを待つようにすることで機能します。送信側は、確認応答を受信した後でのみ次のメッセージを送信します。一方、非同期通信も同期通信の上に構築できます。たとえば、最新のマイクロカーネルは一般的に同期メッセージングプリミティブのみを提供しており、ヘルパースレッドを使用することでその上に非同期メッセージングを実装できます。
メッセージパッシングシステムは、分散オブジェクトまたはローカルオブジェクトのいずれかを使用します。分散オブジェクトの場合、送信者と受信者は異なるコンピュータ上にあり、異なるオペレーティングシステムを実行し、異なるプログラミング言語を使用するなど、さまざまな状況が考えられます。この場合、バス層が、あるシステムから別のシステムへのデータ変換、ネットワークを介したデータの送受信などの詳細を処理します。Unix のリモートプロシージャコール(RPC) プロトコルは、この初期の例です。このタイプのメッセージパッシングでは、送信者も受信者もオブジェクト指向プログラミングを使用する必要はありません。手続き型言語システムは、メッセージの送受信が可能な大きな粒度のオブジェクトとしてラップして扱うことができます。[ 7 ]
分散オブジェクトをサポートするシステムの例としては、Emerald、ONC RPC、CORBA、Java RMI、DCOM、SOAP、.NET Remoting、CTOS、QNX Neutrino RTOS、OpenBinder、D-Busなどがあります。分散オブジェクトシステムは、メッセージパッシングの抽象化によって、メッセージ送信の実装で使用される可能性のある基盤となる状態変化が隠蔽されるため、「共有なし」システムと呼ばれています。
分散型、または非同期型のメッセージパッシングは、プロシージャ呼び出しに比べてオーバーヘッドが大きくなります。メッセージパッシングでは、引数を新しいメッセージにコピーする必要があります。引数によっては数メガバイトのデータが含まれる場合があり、そのすべてをコピーして受信オブジェクトに送信しなければなりません。
従来のプロシージャ呼び出しは、メモリ使用量、転送時間、局所性の点でメッセージパッシングとは異なります。引数は通常、追加の記憶領域や転送時間を必要としない汎用レジスタ、または引数のアドレス(数ビット)を含むパラメータリストによって受信側に渡されます。分散システムでは、システムが別々のアドレス空間を使用するため、アドレスパッシングは不可能です。
ウェブブラウザやウェブサーバーは、メッセージパッシングによって通信を行うプロセスの例です。URLは、プロセスの内部構造を公開することなくリソースを参照する例です。
サブルーチン呼び出しやメソッド呼び出しは、呼び出された計算が終了するまで終了しません。一方、非同期メッセージパッシングでは、要求メッセージが送信されてから応答が到着するまでにかなりの時間がかかる場合があります。
メッセージハンドラは、一般的に複数の送信元からのメッセージを処理します。つまり、その状態は、単一の送信元やクライアントプロセスの動作とは無関係な理由で変化する可能性があります。これは、メソッドが呼び出されるオブジェクトの典型的な動作とは対照的です。後者は、メソッド呼び出しの間、同じ状態を維持することが期待されます。言い換えれば、メッセージハンドラは揮発性オブジェクトと同様の動作をします。
メッセージパッシングの代表的な数学モデルは、アクターモデルとπ計算です。[ 8 ] [ 9 ]数学的には、メッセージはオブジェクトに制御を渡す唯一の手段です。オブジェクトがメッセージに応答する場合、そのメッセージに対応するメソッドを持っています。
アラン・ケイは、オブジェクト指向プログラミングにおいて、オブジェクトよりもメッセージパッシングの方が重要であり、オブジェクト自体が過度に強調されることが多いと主張している。ライブ分散オブジェクトプログラミングモデルはこの観察に基づいており、分散データフローの概念を用いて、高レベルの関数型スタイルの仕様を使用して、複雑な分散システムの動作をメッセージパターンで特徴付ける。[ 10 ]