1.测试代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/msg.h>
#include<unistd.h>
#include<time.h>
#include<sys/ipc.h>
void msg_show(int msg_id,struct msqid_ds msg_info)
{
int ret=-1;
sleep(1);
ret=msgctl(msg_id,IPC_STAT,&msg_info);//get message
if(ret==-1)
{
printf("get message failed!!");
return ;
}
printf("\n");
/*show msg_info*/
printf("the uid of msg is %d\n",msg_info.msg_perm.uid);
printf("the gid of msg is %d\n",msg_info.msg_perm.gid);
printf("现在消息队列中的字节数: %ld\n",msg_info.msg_cbytes);
printf("现在队列中的消息数: %d\n",msg_info.msg_qnum);
printf("现在消息队列中的最大字节数: %d\n",msg_info.msg_qbytes);
printf("最后发送消息的进程: %d\n",msg_info.msg_lspid);
printf("最后接受消息的进程: %d\n",msg_info.msg_lrpid);
printf("最后发送消息的时间: %s\n",ctime(&(msg_info.msg_stime)));
printf("最后接受消息的时间: %s\n",ctime(&(msg_info.msg_rtime)));
printf("最后消息变化的时间: %s\n",ctime(&(msg_info.msg_ctime)));
}
int main()
{
int ret=-1;
int msg_flags,msg_id;
key_t key;
struct msgmbuf
{
int mtype;
char mtext[20];
};
struct msqid_ds msg_info; /*creat msg queue*/
struct msgmbuf msg_mbuf; /*消息缓冲结构*/
char *rpath="/home/18/";
int msg_sflags,msg_rflags;
key=ftok(rpath,'b'); /*create key*/
if(-1!=key)
{
printf("success!!\n");
}
else{
printf("create key failed!\n");
}
msg_flags=IPC_CREAT|IPC_EXCL;
msg_id=msgget(key,msg_flags);
if(-1==msg_id)
{
printf("create msg faided!!\n");
}
msg_show(msg_id,msg_info);
memcpy(msg_mbuf.mtext,"test message",sizeof("test message"));
ret=msgsnd(msg_id,&msg_mbuf,sizeof("test message!!"),IPC_NOWAIT);
if(ret==-1)
printf("send failed!\n");
msg_show(msg_id,msg_info);
msg_rflags=IPC_NOWAIT|MSG_NOERROR;
ret=msgrcv(msg_id,&msg_mbuf,20,0,msg_rflags);
if(-1==ret)
printf("mes receive failed!!\n");
msg_show(msg_id,msg_info);
msg_info.msg_perm.uid=8;
msg_info.msg_perm.gid=8;
msg_info.msg_qbytes=12345;
ret=msgctl(msg_id,IPC_SET,&msg_info);/*set the property of msg*/
if(-1==ret)
{
printf("set failed!!\n");
}
msg_show(msg_id,msg_info);
ret=msgctl(msg_id,IPC_RMID,NULL);
if(ret==-1)
printf("delete failed!!\n");
return 0;
}
2.消息队列结构
什么是消息队列?
消息队列是内核地址空间的内部链表,通过linux各个进程之间传递消息。消息队列通过ipc标识符区分
队列上一个消息的结构
#include<linux/msg.h>
struct msgbuf
{
long mtype; //消息类型
char mtext[1]; //消息内容
}
该结构可以自己定义
消息的大小在msg.h中有限制
#define MSGMAX 8192
消息队列结构
#include<linux/msg.g>
struct msqid_ds
{
struct ipc_perm msg_perm; //队列许可权限信息(访问许可及队列创建者有关信息)
time_t msg_stime; //发送到队列的最后一个消息的时间
time_t msg_rtime; //最后从队列获取消息的时间
time_t msg_ctime; //对队列最后一次变动的时间
unsigned long _msg_cbytes; //队列上的总字节数
msgqnum_t msg_qnum; //队列上的消息数目
msglen_t msg_qbytes; //队列能够容纳的最大字节数
pid_t msg_lspid; //最后一个向队列发消息的进程
pid_t msg_lrpid; //最后一个接收队列消息的进程
};
struct ipc_perm
{
key_t key; //函数msgget()使用的key
uid_t uid; //用户的uid
gid_t gid ; //用户的gid
uid_t cuid; //建立者的uid
gid_t cgdid; //建立者的gid
unsigned short mode; //权限
unsigned short seq; //序列号
};
3.操作函数
键值构建函数
#include<sys/types.h>
#include<sys/ipc.h>
key_t ftok(const char *pathname,int proj_id);
//如:
key_t key;
char *rpath="/ipc/msg/"
key=ftok(rpath,'a');
//第一个参数是已经存在的目录
//第二个参数一般是‘a’,'b'
从队列中获取消息
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgget(key_t key,int msgflag);
//第一个参数是键值,用ftok()生成,拿来与内核中消息队列的值比较
//megflag取值如下:
IPC_CREAT:如果比较过后内核空间没有该消息队列,就创建它
IPC_EXCL:通常与IPC_CREAT一起使用,如msgflag=IPC_CREAT|IPC_EXCL;
//返回值:meg_id==>队列标识符
发送消息函数
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgsnd(int msgqid,const void *msgp,size_t msgsz,int msgflag);
//第一个参数是用msgget得到的标识符
//第二个是指向消息缓冲区
//第三个是消息的大小(以字节为单位),不包含消息类型
//可取值:
0:表示忽略
IPC_NOWAIT:
//返回值:-1表示发送消息失败
接收消息函数
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
ssize_t msgrcv(int msqid,void* msgp,size_t msgsz,logn msgtyp,int msgflg);
//第一个参数指定消息队列
//第二个指向存放消息缓冲区
//第三个缓冲区大小(不包括mtype)
//第四个消息类型(如果为0返回队列中最老的消息)
//第五个
消息控制函数
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
int msgctl(int msqid,int cmd,struct msqid_ds *buf);
//函数用途:向内核发送一个cmd命令,buf为应用层和内核空间数据交换的指针
cmd取值为:
IPC_STAT:获取队列的msqid_ds结构,并把它存在buf地址中
IPC_SET:设置队列的ipc_perm成员值,这个值先存在buf里
IPC_RMID:删除队列