Linuxカーネルにメッセージキューはどのように実装されていますか?


回答:


41

Linuxカーネル(2.6)は、2つのメッセージキューを実装しています(
FIFOの原則に厳密に従っていないリンクリストを使用して実装されるため、「メッセージリスト」ではなく)

System V IPCメッセージ

System Vからのメッセージキュー。

プロセスはmsgsnd()、メッセージを送信するために呼び出すことができます。彼は、受信メッセージキューのIPC識別子、メッセージのサイズ、およびメッセージタイプとテキストを含むメッセージ構造を渡す必要があります。

一方、プロセスはmsgrcv()メッセージを受信するために呼び出し、メッセージが格納されるメッセージキューのIPC識別子、サイズ、および値tを渡します。

tは、キューから返されるメッセージを指定します。正の値は、タイプがtに等しい最初のメッセージが返されることを意味し、負の値は、タイプtに等しい最後のメッセージを返し、ゼロはキューの最初のメッセージを返します。

これらの関数はinclude / linux / msg.hで定義され、ipc / msg.cで実装されます

メッセージのサイズ(最大)、メッセージの合計数(mni)、およびキュー内のすべてのメッセージの合計サイズ(mnb)には制限があります。

$ sysctl kernel.msg{max,mni,mnb}
kernel.msgmax = 8192
kernel.msgmni = 1655
kernel.msgmnb = 16384

上記の出力はUbuntu 10.10システムからのもので、デフォルトはmsg.hで定義されています

ここで説明されている、信じられないほど古いSystem Vメッセージキューのもの。

POSIXメッセージキュー

POSIX標準は、System V IPCのメッセージキューに基づいてメッセージキューメカニズムを定義し、いくつかの機能を拡張しています。

  • アプリケーションへのシンプルなファイルベースのインターフェース
  • メッセージの優先度のサポート
  • 非同期通知のサポート
  • ブロック操作のタイムアウト

ipc / mqueue.cを参照してください

util-linux メッセージキューを分析および変更するためのいくつかのプログラムを提供し、POSIX仕様はいくつかのCの例を提供します。

ipcmk;を使用してメッセージキューを作成します。一般的にはftok()msgget()次のようなC関数を呼び出すことでこれを行います。

$ ipcmk -Q

ipcsまたはを使用して何が起こったかを見てみましょうcat /proc/sysvipc/msg

$ ipcs -q

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x33ec1686 65536      user       644        0            0           

次に、キューにいくつかのメッセージを入力します。

$ cat <<EOF >msg_send.c
#include <string.h>
#include <sys/msg.h> 

int main() {
  int msqid = 65536;
  struct message {
    long type;
    char text[20];
  } msg;

  msg.type = 1;
  strcpy(msg.text, "This is message 1");
  msgsnd(msqid, (void *) &msg, sizeof(msg.text), IPC_NOWAIT);
  strcpy(msg.text, "This is message 2");
  msgsnd(msqid, (void *) &msg, sizeof(msg.text), IPC_NOWAIT);

  return 0;
}
EOF

繰り返しますが、通常、msqidをコードにハードコーディングしません。

$ gcc -o msg_send msg_send.c
$ ./msg_send
$ ipcs -q

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x33ec1686 65536      user       644        40           2        

そして、メッセージを受信する反対側:

$ cat <<EOF >msg_recv.c
#include <stdio.h>
#include <sys/msg.h>

int main() {
  int msqid = 65536;
  struct message {
    long type;
    char text[20];
  } msg;
  long msgtyp = 0;

  msgrcv(msqid, (void *) &msg, sizeof(msg.text), msgtyp, MSG_NOERROR | IPC_NOWAIT);
  printf("%s \n", msg.text);

  return 0;
}
EOF

何が起こるか見てください:

$ gcc -o msg_recv msg_recv.c
$ ./msg_recv
This is message 1
$ ./msg_recv
This is message 2
$ ipcs -q

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages    
0x33ec1686 65536      user       644        0            0           

2回受信すると、キューは再び空になります。

キー(-Q)またはmsqid(-q)を指定して、後で削除します。

$ ipcrm -q 65536

それでは、メッセージ(タイプとテキスト)は複製/コピーされ、そのコピーはシステムのメッセージキューに入れられますか?
trusktr

とてもうまく入れました。この驚くべき説明をありがとう。
User9102d82
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.