C++
 Computer >> コンピューター >  >> プログラミング >> C++

メッセージキューを使ったプロセス間通信(IPC)の基礎と実装方法

共有メモリがあるのに、なぜメッセージキューが必要なのか?

共有メモリという強力なIPC手段がすでにあるのに、なぜメッセージキューが必要なのでしょうか。その理由は複数あります。理解しやすいように、いくつかのポイントに分けて整理してみましょう。

  • メッセージキューでは、あるプロセスがメッセージを受信すると、そのメッセージは他のプロセスからは利用できなくなります。一方、共有メモリでは、複数のプロセスが同じデータに同時にアクセスできます。
  • 小さなサイズのメッセージ形式で通信したい場合に適しています。
  • 共有メモリでは、複数のプロセスが同時に通信する際、同期処理によってデータを保護する必要があります。
  • 共有メモリへの読み書きの頻度が非常に高い場合、機能の実装は複雑になり、利用効率の面で見合わなくなることがあります。
  • すべてのプロセスが共有メモリにアクセスする必要はなく、ごく一部のプロセスだけが必要とする場合には、メッセージキューで実装する方が適切です。
  • 異なる種類のデータパケットで通信したい場合、たとえばプロセスAがプロセスBにはメッセージタイプ1、プロセスCにはメッセージタイプ10、プロセスDにはメッセージタイプ20を送るようなケースでは、メッセージキューの方が実装がシンプルになります。なお、メッセージタイプは1や10、20のような値に限らず、後述するように0・正・負のいずれの値でも構いません。
  • もちろん、メッセージキューの順序はFIFO(First In First Out:先入れ先出し)です。最初にキューへ挿入されたメッセージが、最初に取り出されます。

共有メモリを使うか、メッセージキューを使うかは、アプリケーションの要件と、それぞれの仕組みをどれだけ効果的に活用できるかによって判断しましょう。

メッセージキューによる通信のパターン

メッセージキューを使った通信は、主に以下のようなパターンで行われます。

  • あるプロセスがメッセージキューに書き込み、別のプロセスがそれを読み取るパターン。読み取り側は、複数のプロセスが同時に行うことも可能です。
    メッセージキューを使ったプロセス間通信(IPC)の基礎と実装方法

また、あるプロセスが異なるデータパケットをメッセージキューに書き込み、複数のプロセスがメッセージタイプに応じて、それぞれ必要なメッセージだけを読み取るパターンもあります。

メッセージキューを使ったプロセス間通信(IPC)の基礎と実装方法

メッセージキューを操作するシステムコール(System V)

メッセージキューに関する基本情報を確認したところで、次はメッセージキューをサポートするシステムコール(System V)を見ていきましょう。メッセージキューを使って通信を行うには、以下の手順に従います。

ステップ1 − メッセージキューを作成する、または既存のメッセージキューに接続する(msgget())

ステップ2 − メッセージキューに書き込む(msgsnd())

ステップ3 − メッセージキューから読み取る(msgrcv())

ステップ4 − メッセージキューに対する制御操作を行う(msgctl())

サンプルプログラム

ここでは2つのプロセスを作成します。1つはメッセージを書き込むライター、もう1つはメッセージを読み取るリーダーです。それぞれのプロセスがどのように動作するのか、実際のコードで確認していきましょう。

書き込み側(ライター)のサンプルコード

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// メッセージキュー用の構造体
struct msg_buffer {
    long msg_type;
    char msg[100];
} message;
main() {
    key_t my_key;
    int msg_id;
    my_key = ftok("progfile", 65); // 一意なキーを生成
    msg_id = msgget(my_key, 0666 | IPC_CREAT); // メッセージキューを作成してIDを取得
    message.msg_type = 1;
    printf("Write Message : ");
    fgets(message.msg, 100, stdin);
    msgsnd(msg_id, &message, sizeof(message), 0); // メッセージを送信
    printf("Sent message is : %s \n", message.msg);
}

読み取り側(リーダー)のサンプルコード

#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
// メッセージキュー用の構造体を定義
struct msg_buffer {
    long msg_type;
    char msg[100];
} message;
main() {
    key_t my_key;
    int msg_id;
    my_key = ftok("progfile", 65); // 一意なキーを生成
    msg_id = msgget(my_key, 0666 | IPC_CREAT); // メッセージキューを作成してIDを取得
    msgrcv(msg_id, &message, sizeof(message), 1, 0); // メッセージを受信
    // 受信したメッセージを表示
    printf("Received Message is : %s \n", message.msg);
    msgctl(msg_id, IPC_RMID, NULL); // メッセージキューを削除
    return 0;
}

実行結果

メッセージキューを使ったプロセス間通信(IPC)の基礎と実装方法

  1. C++で双方向リンクリストを使用した優先度付きキューの実装

    整数値のデータと優先度が与えられ、その優先度に従って双方向リンクリスト(doubly linked list)を作成し、結果を表示することが本記事の課題です。 優先度付きキューとは? キュー(Queue)はFIFO(First In, First Out:先入れ先出し)方式のデータ構造であり、最初に挿入された要素が最初に取り出されます。優先度付きキュー(Priority Queue)は、要素の優先度に応じて挿入や削除を行えるキューの一種です。キュー、スタック、リンクリストなどのデータ構造を使って実装でき、本記事では双方向リンクリストを用います。 優先度付きキューは、次のルールに従って動作しま

  2. Truecaller(トゥルーカラー)でメッセージを予約送信する方法【Android対応】

    誰かの誕生日を忘れてしまい、後悔した経験はありませんか?人間ですから、大切な人の記念日であっても、うっかり忘れてしまうことはあります。 しかし、Truecallerを使えば、メッセージを事前に予約送信できるため、特別な日を忘れる心配はもうありません。 Truecallerは、発信者の識別や迷惑電話のブロックを主な機能とする人気アプリですが、それ以外にも通話録音、チャット、ボイスメッセージ、そしてメッセージの予約送信など、便利な機能を多数搭載しています。 この記事では、Truecallerを使ってメッセージを予約送信する方法を詳しく解説します。 Truecallerでメッセージを予約送信する手順