进程间通讯--消息队列
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; /* 消息类型 must be > 0 */ char mtext[1]; /* 消息数据 这里只是一个数组的首地址,并非是只有一个字符 */ };
|
msgrcv()解除阻塞的条件三个条件:
1. 消息队列中有了满足条件的消息(或使用了);
2. msqid代表的消息队列被删除;
3. 调用msgrcv()的进程被信号中断;
a) 发送数据
int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg);
参数 |
说明 |
msqid |
已打开的消息队列id |
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; /* structure describing operation permission */ __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; } }
|
阅读(930) | 评论(0) | 转发(0) |