1.创建(获取)消息队列
msgget()
函数声明: int msgget ( key_t key, int msgflg )
返回值: message queue identifier on success失败的话返回-1
第一个参数:可以自己在开头用define宏定义一个任意数字
第二个参数,msgflg 控制的。它可以取下面的几个值:
IPC_CREAT :
如果消息队列对象不存在,则创建之,否则则进行打开操作;
IPC_EXCL:
和IPC_CREAT 一起使用(用”|”连接),如果消息对象不存在则创建之,否则产生一个错误并返回。
0:如果已经创建了就填入0;
2.读写消息队列
读:msgrcv()
函数原型: int msgrcv ( int msqid, struct msgbuf *msgp, int msgsz, long mtype, int msgflg )
返回值: 成功的话返回拷贝入message buffer的字节数(拷贝入msgsz中的字节数)失败的话就是-1
参数:
P1-int msqid: 消息队列的控制字(ID),用于区别各个消息队列,通过msgget函数获得,以消息队列的键值作为入参(具体键值可自定义)
P2-struct msgbuf *msgp: 指向消息缓冲区的指针,msgrcv中用于存放接收到的消息,msgsnd中用于存放要发送出的消息
(一般是结构体的地址)
P3-int msgsz: 消息的大小(字节数)
P4-long mtype: 值决定返回哪一条消息(等于0 — 返回队列中最早的一条消息;大于0 — 返回类型为mtype的第一条消息;小于0 — 则返回其类型小于或等于mtype参数的绝对值的最小的一个消息)
P5-int msgflg: 是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数
的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。
注:函数的前三个参数和msgsnd()函数中对应的参数的含义是相同的。第四个参数mtype指定了函数从队列中所取的消息的类型。函数将从队列中搜索类型与之匹配的消息并将之返回。不过这里有一个例外。如果mtype 的值是零的话,函数将不做类型检查而自动返回队列中的最旧的消息。
写: msgsnd()
函数声明: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg )
返回值: 成功返回0,失败返回-1
参数:
第一个参数msqid 是消息队列对象的标识符(由msgget()函数得到),第二个参数msgp 指向要发送的消息所在的内存,第三个参数msgsz 是要发送信息的长度(字节数),可以用以下的公式计算:
msgsz = sizeof(struct mymsgbuf) - sizeof(long);
第四个参数是控制函数行为的标志,可以取以下的值:
0,忽略标志位;
IPC_NOWAIT,如果消息队列已满,消息将不被写入队列,控制权返回调用函数的线程。如果不指定这个参数,线程将被阻塞直到消息被可以被写入。
3.销毁消息队列
msgctl()
函数原型:int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
返回值:成功返回0,失败返回-1;
参数:
函数的第一个参数 msgqid 是消息队列对象的标识符。
第二个参数 是函数要对消息队列进行的操作,它可以是:
IPC_STAT
取出系统保存的消息队列的msqid_ds 数据,并将其存入参数buf 指向的msqid_ds 结构中。
IPC_SET
设定消息队列的msqid_ds 数据中的msg_perm 成员。设定的值由buf 指向的msqid_ds结构给出。
IPC_RMID
将队列从系统内核中删除。
这三个命令的功能都是明显的,所以就不多解释了。唯一需要强调的是在IPC_STAT命令中队列的msqid_ds 数据中唯一能被设定的只有msg_perm 成员,其是ipc_perm 类型的
数据。而ipc_perm 中能被修改的只有mode,pid 和uid 成员。其他的都是只能由系统来设定
的。
第三个参数可以设置空指针NULL
写(代码)
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#define MSGKEY 1234
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1024]; /* message data */
};
int main()
{
//创建消息队列
int msgid = msgget(MSGKEY, IPC_CREAT | IPC_EXCL);
if(-1 == msgid)
{
perror("msgget");
exit(1);
}
struct msgbuf m;
int ret;
while(1)
{
m.mtype = 1; //类型
scanf("%s",m.mtext);
ret = msgsnd(msgid,&m,sizeof(m.mtext),0);
if(-1 == ret)
{
perror("msgsnd");
exit(1);
}
if(!strcmp(m.mtext,"bye"))
{
break;
}
memset(m.mtext,0,sizeof(m.mtext));
}
msgctl(msgid, IPC_RMID, NULL); //删除
return 0;
}
读
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#define MSGKEY 1234
struct msgbuf
{
long mtype; /* message type, must be > 0 */
char mtext[1024]; /* message data */
};
int main()
{
//获取消息队列
int msgid = msgget(MSGKEY,0);
if(-1 == msgid)
{
perror("msgged");
exit(1);
}
struct msgbuf m;
int ret;
while(1)
{
ret = msgrcv(msgid,&m,sizeof(m.mtext),1,0);
if(-1 == ret)
{
perror("msgrcv");
exit(1);
}
if(!strcmp(m.mtext, "bye"))
{
break;
}
printf("%s\n", m.mtext);
memset(m.mtext, 0, sizeof(m.mtext));
}
return 0;
}