unix网络编程:System V 消息队列

概述

对于系统中的每个消息队列,内核维护一个定义在 <sys/msg.h> 头文件中的信息结构:

struct msqid_ds {
  // structure describing operation permission
  struct ipc_perm msg_perm;

  // current number of bytes on queue
  unsigned long __msg_cbytes;

  // number of messages currently on queue
  msgqnum_t msg_qnum;

  // max number of bytes allowed on queue
  msglen_t msg_qbytes;


  // pid of last msgsnd()
  pid_t msg_lspid;

  // pid of last msgrcv()
  pid_t msg_lrpid;


  // time of last msgsnd() 
  time_t msg_stime;

  // time of last msgrcv()
  time_t msg_rtime;

  // time of last msgctl()
  time_t msg_ctime;
}

msgget

msgget 用于创建一个新的消息队列或访问一个已存在的消息队列。

code c
#include <sys/msg.h>
int msgget(key_t key, int oflag);

msgget 返回一个整数标识符,其它三个 msg 函数将用该标识符来指代该队列。标识符是基于参数 key 产生的,而 key 既可以是 ftok 的返回值,也可以是常值 IPC_PRIVATE

oflag 为 IPC 机制的权限位:

数字值(八进制) 符号值 说明
消息队列 信号量 共享内存区
0400
0200
MSG_R
MSG_W
SHM_R
SHM_A
SHM_R
SHM_W
由用户(属主)读
由用户(属主)写
0040
0020
MSG_R >> 3
MSG_W >> 3
SHM_R >> 3
SHM_A >> 3
SHM_R >> 3
SHM_W >> 3
由(属)组成员读
由(属)组成员写
0004
0002
MSG_R >> 6
MSG_W >> 6
SHM_R >> 6
SHM_A >> 6
SHM_R >> 6
SHM_W >> 6
由其他用户读
由其他用户写

在此处还可以与 IPC_CREATIPC_IPC_CREAT | IPC_EXCL 按位或,这将会在后续内容讨论。

当创建一个新消息队列时,msqid_ds 结构的如下成员被初始化:

  • msg_perm 结构的 uid 和 cuid 成员被置成当前进程的有效用 ID,gid 和 cgid 被置成当前进程的有效组 ID。

  • oflag 中的读写权限位存放在 msg_perm.mode 中。

  • msg_qnum、msg_lspid、msg_lrpid、msg_stime 和 msg_rtime 被置为 0。

  • msg_ctime 被置成当前时间。

  • msg_qbytes 被置成系统限制值。

msgsnd

使用 msgget 打开一个消息队列后,可以使用 msgsnd 往其上放置一个消息。

code c
#include <sys/msg.h>

// 成功返回 0,出错返回 -1
int msgsnd(int msqid, const void *ptr, size_t length, int flag);

其中 msqid 是 msgget 返回的标识符,ptr 是一个结构体指针,该结构具有以下的模板,定义在 <sys/msg.h> 中:

msgbuf c
struct msgbuf {
  // message type, must be > 0
  long mtype;

  // message data
  char mtext[1];
}

消息类型必须大于 0,因为对于 msgrcv 函数来说,非正的消息类型用做特殊的指示器,这将在后续内容讲述。