Linuxカーネルでメッセージキューがどのように実装されるかを知りたいです。
答え1
Linuxカーネル(2.6)は2つのメッセージキューを実装しています。 (
実装はリンクリストを使用して行われ、先入れ先出しの原則に厳密に従わないため、「メッセージリスト」の代わりに)
システムV IPCメッセージ
System Vのメッセージキュー。
メッセージを送信するためにプロセスを呼び出すことができますmsgsnd()
。彼は、着信メッセージキューのIPC識別子、メッセージサイズ、およびメッセージタイプとテキストを含むメッセージ構造を渡す必要があります。
一方、プロセス呼び出しはmsgrcv()
メッセージを受け取り、メッセージキューのIPC識別子、メッセージを保存する場所、サイズ、および値を渡します。ティー。
ティーキューから返されるメッセージを指定します。正の値は、タイプが次の最初のメッセージを表します。ティー戻り値、負の値はタイプと同じ最後のメッセージを返します。ティー0 はキューの最初のメッセージを返します。
これらの関数は次に定義されています。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システムの出力であり、デフォルト値は次のように定義されています。メッセージ.h。
以前のSystem Vメッセージキューの内容のより驚くべき説明ここ。
POSIXメッセージキュー
POSIX 標準は、System V IPC メッセージキューに基づいてメッセージキューメカニズムを定義し、いくつかの機能を拡張します。
- シンプルなファイルベースのアプリケーションインタフェース
- サポートメッセージの優先順位
- 非同期通知のサポート
- ブロック操作がタイムアウトしました。
バラよりipc/mqueue.c
はい
util-linux
メッセージ・キューを分析および変更するためのいくつかのプログラムが提供されており、POSIX 仕様はいくつかの C 例を提供します。
ipcmk
以下を使用してメッセージキューを作成します。通常、ftok()
次のC関数を呼び出してこれを行いますmsgget()
。
$ ipcmk -Q
ipcs
orを使って何が起こるのか見てみましょう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
次に、key()またはmsqid()を指定して-q
削除します。
$ ipcrm -q 65536