プロセス間通信にメッセージ キューを使用する方法について話しましょう。メッセージ キューには名前付きパイプと多くの類似点があります。名前付きパイプの詳細については、私の他の記事を参照してください: Linux プロセス間通信 - 名前付きパイプの使用
1. メッセージ キューとは
メッセージ キューは、あるプロセスから別のプロセスに通信する方法を提供します。データの塊を送信するため。 各データ ブロックにはタイプが含まれていると見なされ、受信プロセスは異なるタイプを含むデータ構造を独立して受信できます。メッセージを送信することで、名前付きパイプの同期とブロックの問題を回避できます。ただし、メッセージ キューには、名前付きパイプと同様に、データ ブロックごとに最大長制限があります。
Linux は、マクロ MSGMAX および MSGMNB を使用して、メッセージの最大長とキューの最大長を制限します。
2. Linux でのメッセージ キューの使用
Linux は、プロセス間通信を実現するために簡単に使用できる一連のメッセージ キュー関数インターフェイスを提供します。その使用法は、他の 2 つの System V PIC メカニズム、つまりセマフォと共有メモリに似ています。
1. msgget 関数
この関数は、メッセージ キューの作成とアクセスに使用されます。そのプロトタイプは次のとおりです:
-
int msgget(key_t, key, int msgflg);
などIPC メカニズムでは、プログラムは特定のメッセージ キューに名前を付けるためのキーを提供する必要があります。 msgflgは、メッセージキューのアクセス許可を示す許可フラグであり、ファイルのアクセス許可と同じである。 msgflg は IPC_CREAT と OR できます。これは、キーで指定されたメッセージ キューが存在しない場合にメッセージ キューを作成することを意味します。キーで指定されたメッセージ キューが存在する場合、IPC_CREAT フラグは無視され、識別子のみが返されます。
キーで指定されたメッセージ キューの識別子 (ゼロ以外の整数) を返し、失敗した場合は -1 を返します
2
この関数は、メッセージ キューにメッセージを追加するために使用されます。 。そのプロトタイプは次のとおりです:
[cpp]
view plain copy
int msgid,
const - void *msg_ptr,
size _t msg_sz、int msgflg) ;
msgid は、msgget 関数によって返されるメッセージ キュー識別子です。
msg_ptr は送信するメッセージへのポインタですが、メッセージのデータ構造には特定の要件があります。ポインタ msg_ptr が指すメッセージ構造は、受信関数で始まる構造体である必要があります。このメンバーはメッセージのタイプを決定します。したがって、メッセージ構造は次のように定義する必要があります:
[cpp]
view plain copy
-
long
int message _タイプ
-
/* 転送したいデータ*/
msg_sz は、msg_ptr が指すメッセージの長さではないことに注意してください。構造全体の長さ、つまり msg_sz には長整数のメッセージ タイプのメンバー変数の長さは含まれません。
msgflg は、現在のメッセージ キューがいっぱいになった場合、またはキュー メッセージがシステム全体の制限に達した場合に何が起こるかを制御するために使用されます。
呼び出しが成功すると、メッセージ データのコピーがメッセージ キューに配置され、失敗すると -1 が返されます。メッセージのプロトタイプは
です。
[cpp]
普通のコピーを表示
印刷しますか?
-
int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg); msgid、msg_ptr、msg_st関数はmsgsnd関数と同じです。
msgtype は単純な受信優先順位を実装できます。 msgtype が 0 の場合、キュー内の最初のメッセージを取得します。その値が 0 より大きい場合、同じメッセージ タイプの最初のメッセージが取得されます。ゼロ未満の場合は、タイプが msgtype の絶対値以下である最初のメッセージを取得します。
msgflg は、受信するキューに対応するタイプのメッセージがない場合に何が起こるかを制御するために使用されます。
この関数が正常に呼び出されると、受信バッファに置かれたバイト数が返され、メッセージは msg_ptr が指すユーザー割り当てのバッファにコピーされ、その後、メッセージ キュー内の対応するメッセージが削除されます。失敗した場合は -1 を返します。
4. msgctl 関数
この関数は、共有メモリの shmctl 関数に似ています。
プレーンコピーを表示
print?
int msgctl(
int msgid,
int コマンド,
IPC_SET: プロセスに十分な権限がある場合、メッセージ キューの現在関連付けられている値を msgid_ds 構造体で指定された値に設定します
IPC_RMID: メッセージ キューを削除します buf は msgid_ds 構造体へのポインターです。キュー モードとアクセス権の構造のメッセージを指します。 msgid_ds 構造体には少なくとも次のメンバーが含まれます:
[cpp]
view plain copy
print?
struct msgid_ds
{
uid_t shm_perm。 uid;
成功した場合は 0 を返し、失敗した場合は -1 を返します。
3. メッセージを使用するキュー プロセス間通信
ノンストップ。メッセージ キューの定義と使用可能なインターフェイスを紹介した後、プロセス間通信がどのように許可されるかを見てみましょう。無関係なプロセスでも通信できるため、ここでは情報の送受信を表す msgreceive と msgsned という 2 つのプログラムを作成します。通常の状況では、両方のプログラムがメッセージを作成することを許可しますが、最後のメッセージを受信した後に削除するのは受信者だけです。
情報を受け取るプログラムのソースファイルは msgreceive.c で、ソースコードは次のとおりです: -
[cpp]- view plain copy
print?
#include
#include
#include
#include
#include
#include
struct msg_st
{
long int msg_type;
char text[BUFSIZ];
};
int main()
{
int running = 1;
int msgid = -1;
struct msg_st データ;
long int msgtype = 0;
msgid = msgget((key_t)1234, 0 666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget 失敗 エラー: %dn" 、エラー番号);
終了(EXIT_FAILURE);
}
-
while(running)
{
if(msgrcv(msgid ,(void*)&data, BUFSIZ, msgtype, 0) == -1)
{
fprintf(stderr, "msgrcv failed)エラー番号あり: %dn", エラー番号);
終了(EXIT_FAILURE);
}
printf("あなたが書きました: %sn",data.text);
-
if(strncmp(data.text, "end", 3) == 0)
実行中 = 0;
}
if(msgctl(msgid, IPC_RMID, 0) == -1)
{
fprintf(stderr, 「msgctl(IPC_RMID) が失敗しました」);
終了(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
送信送信情報の手順のソース文件msgsend.cのソース代码:
#include
#include
#include
#include
#include
#include
#define MAX_TEXT 512
struct msg_st
{
-
long int msg_type;
char text[MAX_TEXT];
};
int main()
{
int running = 1;
struct msg_st データ;
char バッファ[BUFSIZ];
int msgid = -1;
msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
if(msgid == -1)
{
fprintf(stderr, "msgget 失敗 エラー: %dn" 、エラー番号);
終了(EXIT_FAILURE);
}
while(running)
{
printf("Enter some text: ");
fgets(buffer, BUFSIZ, stdin);
data.msg_type = 1;
strcpy(data.text, buffer);
if(msgsnd(msgid, (void*)&data, MAX_TEXT, 0) == -1)
{
fprintf(stderr, "msgsnd 失敗");
終了(EXIT_FAILURE);
}
if(strncmp(buffer, "end") , 3) == 0)
実行中 = 0;
睡眠(1);
}
exit(EXIT_SUCCESS);
}
运行结果如下:
IV. 分析例 - メッセージタイプ
ここでは主に、msgreceive.c ファイルの main 関数で定義されている変数 msgtype に注目して説明します。注 1) として注釈が付けられており、msgrcv 関数の受信情報タイプ パラメーターの値として使用され、その値は 0 で、キュー内で最初に使用可能なメッセージを取得することを意味します。 msgsend.c ファイルの while ループ内のステートメント data.msg_type = 1 を見てみましょう (注 2)。これは、送信される情報の情報タイプを設定するために使用されます。つまり、送信される情報のタイプは 1 です。 。したがって、プログラム msgceive は、プログラム msgsend によって送信された情報を受信できます。
注 1、つまり、msgreceive.c ファイルの main 関数内のステートメントが、long int msgtype = 0; から long int msgtype = 2; に変更されると、msgreceive は受信できなくなります。プログラム msgsend によって送信される情報。 msgrcv 関数を呼び出すときに、msgtype (4 番目のパラメーター) が 0 より大きい場合、変更後に取得されるメッセージ タイプは同じメッセージ タイプを持つ最初のメッセージのみが取得され、msgsend によって送信されるメッセージ タイプは 2 になります。 1. そのため、msgreceive プログラムでは受信できません。 msgreceive.c ファイルを再コンパイルして再度実行すると、結果は次のようになります。
msgreceive が情報を受信して出力せず、msgsend 入力終了時に msgreceive が終了しないことがわかります。 . jobs コマンドを使用すると、まだバックグラウンドで実行されていることがわかります。
5. メッセージ キューと名前付きパイプの比較
メッセージ キューと名前付きパイプには多くの類似点があります。メッセージ キューを介して通信するプロセスはすべて、送信と送信によってデータを送信します。受け取り中。名前付きパイプでは、データの送信に write が使用され、データの受信に read が使用されます。メッセージ キューでは、データの送信に msgsnd が使用され、データの受信に msgrcv が使用されます。また、各データには最大長制限があります。
名前付きパイプと比較して、メッセージ キューの利点は次のとおりです。 1. メッセージ キューは送信プロセスと受信プロセスから独立して存在することもできるため、名前付きパイプの開始と終了を同期する際に発生する可能性のある問題が排除されます。 2. 同時に、メッセージを送信することで、名前付きパイプの同期とブロックの問題も回避でき、プロセス自体が同期メソッドを提供する必要はありません。 3. 受信プログラムは、名前付きパイプのようにデフォルトでデータを受信するだけでなく、メッセージ タイプを通じてデータを選択的に受信できます。
以上がメッセージキューとは何ですか? Linux でのメッセージ キューの使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。