消息队列特点:
1.消息队列是IPC对象的一种
2.消息队列由消息队列ID来唯一标识
3.消息队列就是一个消息的列表。用户可以再消息队列中添加消息、读取消息等。
4.消息队列可以按照类型来发送/接受消息
消息队列常用的四个函数
函数 作用 参数属性 int msgget(key_t key, int msgflg);
创建消息列表 key:IPC_PRIVATE(亲缘进程)或ftok(非亲缘进程)
msgflg:IPC_CREAT | xxxx(权限,如0777)
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
消息队列添加消息 msqid:消息队列id
msgp:消息结构体首地址
msgsz:消息大小
msgflg:0(发送完才返回)
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
读取消息队列消息 msqid:消息队列id
msgp:消息结构体首地址
msgsz:消息大小
msgtyp:结构体中的消息类型
msgflg:0(读完才返回)
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
删除消息队列 msqid:消息队列id
cmd:操作命令IPC_RMID(删除操作)、IPC_STAT(获取属性)、IPC_SET(设置操作)
buf:NULL(默认操作)
头文件:#include <sys/types.h>、 #include <sys/ipc.h>、#include <sys/msg.h>
通过消息队列实现进程间通信
msgget_write.c
#include <stdio.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h> #include <string.h> #define SIZE 128 typedef struct msgbuf{ long mtype; char mtext[SIZE]; }MSG;//初始化消息结构体 int main(int argc,char *argv[]) { key_t key = ftok(".",'a');//获取key密钥 if(key<0) { perror("ftok"); return -1; } int msgid = msgget(key,IPC_CREAT | 0777);//创建消息队列 if(msgid <0 ) { perror("msgget"); return -1; } printf("msgid:%d\n",msgid); MSG msg1,msg2,msg3; msg1.mtype = 1;//消息类型 strcpy(msg1.mtext,"msg1");//数据拷贝到结构体数组中 msg2.mtype =2; strcpy(msg2.mtext,"msg2"); msg3.mtype =3; strcpy(msg3.mtext,"msg3"); if(msgsnd(msgid,&msg1,sizeof(MSG)-sizeof(long),0) < 0)//添加消息到列表里 { perror("msgsnd"); return -1; } if(msgsnd(msgid,&msg2,sizeof(MSG)-sizeof(long),0) < 0) { perror("msgsnd"); return -1; } if(msgsnd(msgid,&msg3,sizeof(MSG)-sizeof(long),0) < 0) { perror("msgsnd"); return -1; } return 0; }
msgget_read.c
#include <stdio.h> #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h> #include <string.h> #define SIZE 128 typedef struct msgbuf{ long mtype; char mtext[SIZE]; }MSG; int main(int argc,char *argv[]) { key_t key = ftok(".",'a'); if(key<0) { perror("ftok"); return -1; } int msgid = msgget(key,IPC_CREAT | 0777); if(msgid <0 ) { perror("msgget"); return -1; } printf("msgid:%d\n",msgid); MSG msg1,msg2,msg3; if(msgrcv(msgid,&msg1,sizeof(MSG)-sizeof(long),2,0) == -1)//读消息队列里的内容 { perror("msgsnd"); return -1; } printf("%s\n",msg1.mtext); if(msgctl(msgid,IPC_RMID,NULL) == -1)//删除消息队列 { perror("msgctl"); return -1; } return 0; }
注意:
在两个.c文件中的ftok()函数中的参数要相同,不然创建的key密钥不同使得两个进程无法通信,它是两个进程能通信的关键。( key_t key = ftok(".",'a'); )