编程接口指南

System V 消息

必须先通过 msgget(2) 初始化队列,然后进程才能发送或接收消息。 队列的属主或创建者可以使用 msgctl(2) 更改队列的拥有权或权限。 任何具有相应权限的进程均可使用 msgctl(2) 执行控制操作。

通过 IPC 消息传送,进程可以发送和接收消息以及对消息进行排队,以便按任意顺序处理。 与管道的文件字节流数据流不同,每条 IPC 消息都具有显式长度。

可以为消息指定特定类型。 因此通过使用客户机进程 PID 作为消息类型,服务器进程可以将客户机的消息流量分散到其队列中。 对于单消息事务,多个服务器进程可以并行处理发送到共享消息队列的事务。

发送和接收消息的操作分别通过 msgsnd(2)msgrcv(2) 执行。 发送消息时,会将消息的文本复制到消息队列。msgsnd(2)msgrcv(2) 可以作为阻塞操作和非阻塞操作执行。 被阻塞的消息操作将保持暂停状态,直到出现以下三种情况之一:

初始化消息队列

msgget(2) 可初始化新的消息队列, 并且还可返回对应于密钥参数的队列的消息队列 ID (msqid)。 作为 msgflg 参数传递的值必须为八进制整数,并具有该队列的权限和控制标志的设置。

MSGMNI 内核配置选项确定内核支持的单一消息队列数的最大个数。如果超过此限制,msgget(2) 会失败。

以下代码说明了 msgget(2)

#include <sys/ipc.h>

 #include <sys/msg.h>



 ...

 	key_t	key;		/* key to be passed to msgget() */

 	int	msgflg,	/* msgflg to be passed to msgget() */

 			msqid;	/* return value from msgget() */

 	...

 	key = ...

 	msgflg = ...

 	if ((msqid = msgget(key, msgflg)) == -1)

 	{

 		perror("msgget: msgget failed");

 		exit(1);

 	} else

 		(void) fprintf(stderr, "msgget succeeded");

 	...

控制消息队列

msgctl(2) 可更改消息队列的权限和其他特性。 msqid 参数必须为现有消息队列的 ID。 cmd 参数为以下各项之一:

IPC_STAT

将有关队列状态的信息放入 buf 指向的数据结构中。 进程必须具有读取权限,此调用才会成功。

IPC_SET

设置消息队列的属主用户和组 ID、权限以及大小(以字节数为单位)。 进程必须具有属主、创建者或超级用户的有效用户 ID,此调用才会成功。

IPC_RMID

删除 msqid 参数所指定的消息队列。

以下代码说明了 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) 分别发送和接收消息。 msqid 参数必须为现有消息队列的 ID。 msgp 参数是指向包含消息类型及其文本的结构的指针。 msgsz 参数以字节为单位指定消息的长度。 msgflg 参数传递各种控制标志。

以下代码说明了 msgsnd(2)msgrcv(2)

#include <sys/types.h>

 #include <sys/ipc.h>

 #include <sys/msg.h>



 ...

 	int				msgflg;	/* message flags for the operation */

 	struct msgbuf 	*msgp;	/* pointer to the message buffer */

 	size_t			msgsz;	/* message size */

		size_t			maxmsgsize;

 	long				msgtyp;	/* desired message type */

 	int				msqid		/* message queue ID to be used */

 	...

 	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");

 		...