接收部分的代码
//大部分其实都是类似的,
Code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <linux/msg.h>
#define MAXMSG 512
struct my_msg
{
long int my_msg_type;
char some_text[MAXMSG ];
}msg;
int main (int argc, char *argv[])
{
int msgid ;
long int msg_to_receive=0;
char buffer[BUFSIZ];
msgid=msgget( 1234,0666|IPC_CREAT);
//这里再补充下,IPC_CREAT标志仅在该消息对列不存在的情况下创建新的消息队列
while(1)
{
msgrcv(msgid,&msg,BUFSIZ,msg_to_receive,0);
//msg_to_receive的值为0,表明直接从消息队列最前端获取消息
//若此出的值>0,则表示获取类型为与其值相同的第一个消息
//若此值<0,则表示获取小于或等于此值的绝对值的第一个消息
//利用此值的不同可以获取指定类型的消息!这一点非常灵活.
printf("You wrote:%s",msg.some_text);
if( strncmp(msg.some_text,"end",3)==0 )
{
break;
}
}
msgctl(msgid,IPC_RMID,0);
//删除消息队列,最后的0表示不使用查询结果缓冲区,一般在IPC_STATE操作时会定义一个结构体,
//用来传递消息队列的相关信息,此处不使用,直接置0,就行了.
return(0);
}
消息队列的结构
//这一块因为排版的问题,取消了部分文字。。。。
排版总是有问题,放在code里也不行,大致是ipc_id指针指向ipc_id[n]再通过kern_ipc_perm*指向msg_queue中的kern_ipc_perm
上面的是从网上找到的关于这一部分结构的讲解,有助于这一部分的理解
但我在查看了linux内核源码之后发现还是有些出入,可能是因为版本的问题
struct ipc_ids {
int in_use;
unsigned short seq;
unsigned short seq_max;
struct rw_semaphore rw_mutex;
struct idr ipcs_idr;
};
ipc_id的结构未能找到.
struct msg_queue {
struct kern_ipc_perm q_perm;
time_t q_stime; /* last msgsnd time */
time_t q_rtime; /* last msgrcv time */
time_t q_ctime; /* last change time */
unsigned long q_cbytes; /* current number of bytes on queue */
unsigned long q_qnum; /* number of messages in queue */
unsigned long q_qbytes; /* max number of bytes on queue */
pid_t q_lspid; /* pid of last msgsnd */
pid_t q_lrpid; /* last receive pid */
struct list_head q_messages;
//struct list_head 是linux内核实现的双向链表结构,已经实现了一定的操作
struct list_head q_receivers;
struct list_head q_senders;
//这里面用三个双链表来记录消息的本身,发送者和接收者
};
struct kern_ipc_perm
{
spinlock_t lock;
int deleted;
int id;
key_t key;
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
unsigned long seq;
void *security;
};
消息队列的操作
1、 打开(获取)或创建消息队列
2、 读写操作
3、 获得或设置消息队列属性
具体对应如下API(只列出常用的)
1)int msgget(key_t key, int msgflg) -->获取或创建
2)int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg);
-->消息的接收(截获)
3)int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg);
-->消息的发送
4)int msgctl(int msqid, int cmd, struct msqid_ds *buf);
-->消息的控制(状态获取,属性设置,队列的销毁)
具体怎么用不在这里列出,可以参考前面的程序和manpages
另外在使用消息队列时,要通过一结构体告知系统其具体的类型
这一步是需要自己定义的,
struct msgbuf{
long mtype; //消息的类型
char mtext[1]; //消息的内容
};
当然也可以使用单独的变量.
最后,再转一段网上搜来的代码,
虽然丰富了些,但个人感觉,就学习理解而言不如前面的代码
Code
#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>
void msg_stat(int,struct msqid_ds );
main()
{
int gflags,sflags,rflags;
key_t key;
int msgid;
int reval;
struct msgsbuf{
int mtype;
char mtext[1];
}msg_sbuf;
struct msgmbuf
{
int mtype;
char mtext[10];
}msg_rbuf;
struct msqid_ds msg_ginfo,msg_sinfo;
char* msgpath="/unix/msgqueue";
key=ftok(msgpath,'a');
gflags=IPC_CREAT|IPC_EXCL;
msgid=msgget(key,gflags|00666);
if(msgid==-1)
{
printf("msg create error"n");
return;
}
//创建一个消息队列后,输出消息队列缺省属性
msg_stat(msgid,msg_ginfo);
sflags=IPC_NOWAIT;
msg_sbuf.mtype=10;
msg_sbuf.mtext[0]='a';
reval=msgsnd(msgid,&msg_sbuf,sizeof(msg_sbuf.mtext),sflags);
if(reval==-1)
{
printf("message send error"n");
}
//发送一个消息后,输出消息队列属性
msg_stat(msgid,msg_ginfo);
rflags=IPC_NOWAIT|MSG_NOERROR;
reval=msgrcv(msgid,&msg_rbuf,4,10,rflags);
if(reval==-1)
printf("read msg error"n");
else
printf("read from msg queue %d bytes"n",reval);
//从消息队列中读出消息后,输出消息队列属性
msg_stat(msgid,msg_ginfo);
msg_sinfo.msg_perm.uid=8;//just a try
msg_sinfo.msg_perm.gid=8;//
msg_sinfo.msg_qbytes=16388;
//此处验证超级用户可以更改消息队列的缺省msg_qbytes
//注意这里设置的值大于缺省值
reval=msgctl(msgid,IPC_SET,&msg_sinfo);
if(reval==-1)
{
printf("msg set info error"n");
return;
}
msg_stat(msgid,msg_ginfo);
//验证设置消息队列属性
reval=msgctl(msgid,IPC_RMID,NULL);//删除消息队列
if(reval==-1)
{
printf("unlink msg queue error"n");
return;
}
}
void msg_stat(int msgid,struct msqid_ds msg_info)
{
int reval;
sleep(1);//只是为了后面输出时间的方便
reval=msgctl(msgid,IPC_STAT,&msg_info);
if(reval==-1)
{
printf("get msg info error"n");
return;
}
printf(""n");
printf("current number of bytes on queue is %d"n",msg_info.msg_cbytes);
printf("number of messages in queue is %d"n",msg_info.msg_qnum);
printf("max number of bytes on queue is %d"n",msg_info.msg_qbytes);
//每个消息队列的容量(字节数)都有限制MSGMNB,值的大小因系统而异。在创建新的消息队列时,//msg_qbytes的缺省值就是MSGMNB
printf("pid of last msgsnd is %d"n",msg_info.msg_lspid);
printf("pid of last msgrcv is %d"n",msg_info.msg_lrpid);
printf("last msgsnd time is %s", ctime(&(msg_info.msg_stime)));
printf("last msgrcv time is %s", ctime(&(msg_info.msg_rtime)));
printf("last change time is %s", ctime(&(msg_info.msg_ctime)));
printf("msg uid is %d"n",msg_info.msg_perm.uid);
printf("msg gid is %d"n",msg_info.msg_perm.gid);
}