进程间通讯--消息队列
1. 创建消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg); |
成功返回队列ID,失败返回-1。
参数 | 说明 |
key | 创建/打开队列key值,由ftok产生,可以直接给常量 |
msgflg | 创建/打开方式IPC_CREAT、IPC_EXCL、IPC_NOWAIT |
通常是msgflg =IPC_CREAT| IPC_EXCL|0666,意思是若不存在key值的队列则创建,否则如果存在则打开队列,0666意思与一般文件权限一样,XXX-本用户,同组用户,其他用户的读写执行的权限。
# include <sys/types.h>
# include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id); |
//获取pathname相对应的一个键值, pathname必须是存在并且可读取的文件,proj_id表示序号,用来区别同时的存在文件。成功返回key值,失败返回-1。
2. 队列读写
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h> |
a) 读取数据――阻塞读取消息队列,直到解除阻塞。
ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg); |
参数 | 说明 |
msqid | 已打开的消息队列id |
msgp | 接收存放的消息队列缓存结构 |
msgsz | 消息数据长度 |
msgtyp | 消息类型。=0 读取队列中第一个数据。 |
msgflg | 读取标志通常使用IPC_NOWAIT:即没有满足条件的消息,立即返回,此时,错误代码errno=ENOMSG IPC_EXCEPT:与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息 MSG_NOERROR:截断超长数据 |
缓冲内容结构如下:
struct msgbuf {
long mtype;
char mtext[1];
}; |
msgrcv()解除阻塞的条件三个条件:
1. 消息队列中有了满足条件的消息(或使用了);
2. msqid代表的消息队列被删除;
3. 调用msgrcv()的进程被信号中断;
a) 发送数据
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
参数 | 说明 |
msqid | 已打开的消息队列id |
ght: windowtext 1pt solid; padding-right: 5.4pt; border-top: #ece9d8; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 99pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent;" width="132" valign="top"> msgp | 发送存放的消息队列缓存结构 |
msgsz | 消息数据长度 |
msgflg | 消息类型。=0 读取队列中第一个数据。 |
3. 消息队列控制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf); |
成功返回0,失败返回-1。
参数 | 说明 |
msqid | 已打开的消息队列id |
cmd | 控制类型选项 IPC_STAT:取得队列状态 IPC_SET:设置队列属性 IPC_RMID:删除消息队列 |
buf | 存放队列的属性结构 |
队列属性如下:
struct msqid_ds
{
struct ipc_perm msg_perm;
__time_t msg_stime;
unsigned long int __unused1;
__time_t msg_rtime;
unsigned long int __unused2;
__time_t msg_ctime;
unsigned long int __unused3;
unsigned long int __msg_cbytes;
msgqnum_t msg_qnum;
msglen_t msg_qbytes;
__pid_t msg_lspid;
__pid_t msg_lrpid;
unsigned long int __unused4;
unsigned long int __unused5;
}; |
4.例子:
#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>
#define msgkey 0x11000001
struct msg_buf
{
int mtype;
char data[255];
};
int main()
{
key_t key;
int msgid;
int ret;
struct msg_buf msgbuf;
key=ftok("/tmp/1",'a');
printf("key =[%x]/n",key);
//msgid=msgget(key,IPC_CREAT|IPC_EXCL|0666);
msgid=msgget(msgkey,IPC_CREAT|IPC_EXCL|0666);
if(msgid==-1)
{
printf("create error/n");
return -1;
}
msgbuf.mtype = getpid();
strcpy(msgbuf.data,"test haha");
ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);
if(ret==-1)
{
printf("send message err/n");
return -1;
}
memset(&msgbuf,0,sizeof(msgbuf));
ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);
if(ret==-1)
{
printf("recv message err/n");
return -1;
}
printf("recv msg =[%s]/n",msgbuf.data);
ret=msgctl(msgid,IPC_RMID,NULL);//删除消息队列
if(ret==-1)
{
printf("del msg err/n");
return -1;
}
} |
进程间通讯信息查看:
ipcs -q --查看消息队列信息,具体 man ipcs可以看到更多的内容