您的位置:首页 > 运维架构 > Linux

System V消息队列

2015-10-01 17:52 357 查看
System V消息队列使用消息队列标识符标识,与POSIX一样,具有足够权限的进程可以往队列发送消息,具有足够特权的进程可以从一个给定队列读取信息,其具有随内核的持续性。与管道不一样的是,发送下一个消息前不要求某个进程正在等待上一个消息的到达。下面介绍下相关函数:

1)        头文件:<sys/msg.h>

2)        创建或访问消息队列:

int msget(key_t key, int oflag); //成功返回非负标识符,若出错则为-1

其中key既可以是ftok的返回值也可以使IPC_PRIVATE(将创建一个唯一的IPC键);oflag是读写权限的组合(MSG_R, MSG_W),还可以与IPC_CREAT或IPC_EXCL按位或。当创建一个新消息队列时,msqid_ds结构的相关成员将被初始化。

p.s:

system V IPC采用key_t值作为它们的名字。头文件<sys/types.h>把key_t这个数据类型定义为一个整数(通常>=32bit),这些整数是由ftok函数赋予的。ftok函数定义在<sys/ipc.h>中,用于把一个已存在的路径名和一个整数标识符转换成key_t值,成为IPC键。

key_t ftok(const char *pathname, int id);//成功返回ipc键,失败返回-1(当路径不存在或权限不足会失败)

3)        发送消息:

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

其中ptr是一个结构,该结构指示了消息的类型(必须有,消息类型必须大于0)及数据信息。其模版如下:

struct msgbuf{

long mtype;

int iData; //int 型数据,这个是数据信息,szData同样也是

char szData[DATA_LEN];   //数据信息由用户自定义,可以是多种类型也可混合组成

};

length参数为待发送消息的长度(不含消息类型);flag参数可以是0(阻塞)或IPC_NOWAIT(非阻塞,当没有存放新消息的空间时立即返回,返回EAGAIN错误)

4)        接收消息:

ssize_t msgrcv(int msqid, void *ptr, size_tlength, long type, int flag); //成功返回读取字节数,失败-1

其中ptr指定接收消息的存放位置,类型同msgsnd消息(即struct msgbuf);length指示了ptr的缓冲区大小(不含消息类型);type可以指示接收的消息类型(与POSIX消息队列不同的是可以指定类型接收;POSIX消息队列采用的是优先级——只能返回最高优先级,而System V采用的是消息类型);flag除了指定阻塞和非阻塞标识外还可以指定为MSG_NOERROR,用于当接收消息的真正数据部分大于length参数时,可以截断数据部分,返回实际接收的字节数,而不返回错误(未指定的话则返回E2BIG错误)

5)        控制操作:

int msgctl(int msqid, int cmd, structmsqid_ds &buff); //成功返回0,失败-1

cmd可取:

IPC_RMID:删除msqid消息队列,未处理的消息会被丢弃,这时第三个参数忽略

IPC_SET:设置msqid_ds属性为buff所指定的内容的4个成员:msg_perm.uid/gid/mode/qbytes(uid、gid、读写权限和最大消息队列字节数)

IPC_STAT:返回消息队列对应的msqid_ds结构

6)        示例程序:

#include   "stdio.h"
#include "sys/msg.h"
#define MSG_W (0400)
#define MSG_R (0200)
#define ulong_t unsigned long
//permission for message queues 660
#define SVMSG_MODE (MSG_R | MSG_W | MSG_R>> 3 | MSG_W >> 3)
struct msgbuf{
long mtype;
char mtext[100];
};
int main(int argc, char **argv)
{
int                                msqid;
structmsqid_ds       info;
structmsgbuf  buf;

msqid= msgget(ftok("/tmp/msgq.2", 0), SVMSG_MODE | IPC_CREAT);

buf.mtype= 1;
buf.mtext[0]= '1';
buf.mtext[1]= '2';
buf.mtext[1]= '\0';
msgsnd(msqid,&buf, 3, 0);
structmsgbuf buff1;
intn = msgrcv(msqid, &buff1, 1, 1, MSG_NOERROR);
printf("msgrcv%d bytes, msg = %s\n", n, buff1.mtext);
msgctl(msqid,IPC_STAT, &info);
printf("read-write:%03o, cbytes = %lu, qnum = %lu, qbytes = %lu\n",
info.msg_perm.mode & 0777, (ulong_t)info.msg_cbytes,
(ulong_t) info.msg_qnum, (ulong_t)info.msg_qbytes);

system("ipcs-q");   //provide infomation onmessage queues

msgctl(msqid,IPC_RMID, NULL);  //remove it
exit(0);
}


运行结果:

------ Message Queues --------

key       msqid      owner      perms     used-bytes   messages       

0x00006858 458760     hy        644        21           7          

 

msgrcv 1 bytes, msg = 1

read-write: 644, cbytes = 21, qnum = 7,qbytes = 65536
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息