システムインタフェース

System V メッセージ

プロセスがメッセージを送受信できるようにするには、msgget(2) 関数によって待ち行列を初期化しなければなりません。待ち行列の所有者または作成者は、msgctl(2) を使用して、その所有権またはアクセス権を変更できます。また、そうするためのアクセス権を持つプロセスは、制御操作のために msgctl(2) を使用することもできます。

IPC メッセージを使用すると、プロセスはメッセージを送受信し、メッセージを任意の順序で処理待ち行列に入れることができます。パイプで使用されるファイルバイトストリームのモデルによるデータフローとは異なり、IPC メッセージでは長さが明示されます。

メッセージには特定のタイプを割り当てることができます。このため、サーバプロセスは、クライアント PID をメッセージタイプとして使用して、その待ち行列上のクライアント間にメッセージトラフィックを振り向けることができます。単一メッセージトランザクションでは、複数のサーバプロセスは、共用メッセージ待ち行列に送られるトランザクション群に対して、並行して働くことができます。

メッセージの送受信操作は、それぞれ msgsnd(2) 関数と msgrcv(2) 関数によって実行されます。メッセージが送信されると、そのテキストがメッセージ待ち行列にコピーされます。msgsnd(2) 関数と msgrcv(2) 関数は、ブロッキング操作としても非ブロッキング操作としても実行できます。ブロッキングされたメッセージ操作は、次の条件のどれかが生じるまで中断されます。

メッセージ待ち行列の初期化

msgget(2) 関数は、新しいメッセージ待ち行列を初期化します。また、key 引数に対応する待ち行列のメッセージ待ち行列 ID (msgid) を戻します。msgflg 引数として渡される値は、待ち行列アクセス権と制御フラグを設定する 8 進数の整数でなければなりません。

MSGMNI カーネル構成オプションは、カーネルがサポートする固有のメッセージ待ち行列の最大数を指定します。この制限を越えると、msgget(2) 関数は失敗します。次に、msgget(2) 関数の使用例を示します。


#include <sys/ipc.h>
 #include <sys/msg.h>

 ...
 	key_t	key;		/* msgget() に渡す key */
 	int	msgflg,	/* msgget() に渡す msgflg */
 			msqid;	/* msgget() からの戻り値 */ 	...
 	key = ...
 	msgflg = ...
 	if ((msqid = msgget(key, msgflg)) == -1)
 	{
 		perror("msgget: msgget failed");
 		exit(1);
 	} else
 		(void) fprintf(stderr, "msgget succeeded");
 	...

メッセージ待ち行列の制御

msgctl(2) 関数は、メッセージ待ち行列のアクセス権やその他の特性を変更します。msgid 引数は、既存のメッセージ待ち行列の ID でなければなりません。cmd 引数は、次のいずれか 1 つです。

IPC_STAT

待ち行列の状態についての情報を buf が指すデータ構造体に入れる。この呼び出しを行うには、プロセスが読み取り権を持っていなければならない。

IPC_SET

所有者のユーザ ID とグループ ID、アクセス権、およびメッセージ待ち行列の大きさ (バイト数) を設定する。この呼び出しを行うには、プロセスが所有者、作成者、またはスーパーユーザの有効なユーザ ID を持っていなければならない。

IPC_RMID

msgid 引数で指定したメッセージ待ち行列を削除する。

次に、msgctl(2) に各種のフラグをすべて付けて使用する例を示します。


#include			<sys/types.h>
#include			<sys/ipc.h>
#include			<sys/msg.h>

 	...
 	if (msgctl(msqid, IPC_STAT, &buf) == -1)  {
 		perror("msgctl: msgctl failed");
 		exit(1);
 	}
 	...
 	if (msgctl(msqid, IPC_SET, &buf) == -1) {
 		perror("msgctl: msgctl failed");
 		exit(1);
 	}
 	...

メッセージの送受信

msgsnd(2)msgrcv(2) 関数は、それぞれメッセージを送受信します。msgid 引数は、既存のメッセージ待ち行列の ID でなければなりません。msgp 引数は、メッセージのタイプとテキストを含んでいる構造体へのポインタです。msgsz 引数は、メッセージの長さをバイト数で指定します。msgflg 引数には、様々な制御フラグを渡すことができます。

次に、msgsnd(2)msgrcv(2) の使用例を示します。


#include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>

 ...
 	int				msgflg;	/* 操作用のメッセージフラグ */
 	struct msgbuf 	*msgp;	/* メッセージバッファへのポインタ */
 	size_t			msgsz;	/* メッセージの長さ */
		size_t			maxmsgsize;
 	long				msgtyp;	/* 希望するメッセージタイプ */
 	int				msqid		/* 使用するメッセージ待ち行列の ID */
 	...
 	msgp = malloc(sizeof(struct msgbuf) - sizeof (msgp->mtext) 
							+ maxmsgsz);
 	if (msgp == NULL) {
 		(void) fprintf(stderr, "msgop: %s %ld byte messages.¥n",
 				"could not allocate message buffer for", maxmsgsz);
 		exit(1);
 		...
 		msgsz = ...
 		msgflg = ...
 		if (msgsnd(msqid, msgp, msgsz, msgflg) == -1)
 			perror("msgop: msgsnd failed");
 		...
 		msgsz = ...
 		msgtyp = first_on_queue;
 		msgflg = ...
 		if (rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) == -1)
 			perror("msgop: msgrcv failed");
 		...