1.消息队列是啥?
消息队列就是一个消息的链表。就是把消息看作一个记录,并且这个记录具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以按照一定的规则添加新消息;对消息队列有读权限的进程则可以从消息队列中读出消息。
2.消息队列的特点:
1.发送方不必等待接收方检查它所收到的消息就可以继续工作下去,而接收方如果没有收到消息也不需等待(异步)。
2.新的消息总是放在队列的末尾,接收的时候并不总是从头来接收,可以从中间来接收。
3.消息队列随内核和进程相关,只有在内核重启或者显式删除一个消息队列时,该消息队列才会真正被删除。
3.消息队列的使用步骤:(函数的使用)
(1)msgget:得到一个消息队列,当这个消息队列存在的时候, 这个消息调用负责返回这个队列的标识号;如果这个队列不存在,就创建一个消息队列,然后返回这个消息队列的标识号 (2)msgsnd:向一个消息队列发送一个消息
(3)msgrcv:从一个消息队列中收到一个消息
(4)msgctl:在消息队列上执行指定的操作。根据参数的不同和权限的不同,可以执行检索、删除等的操作
4.函数的原型 参数 功能 返回值
msgget--得到一个消息队列
头文件:#include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
函数原型:int msgget (key_t key, int msgflg);
参数:key 为由 ftok 创建的 key 值,msgflg 的低位用来确定消息队列的访问权限,如 0770。还可以附加以下参数值: IPC_CREAT 00001000//如果 key不存在,创建 IPC_EXCL 00002000//如果 key 存在,返回失败 IPC_NOWAIT 00004000 //如果需要等待,直接返回错误
返回值:成功返回IPC标识符,不成功返回-1
5.msgsnd()--发送信息到消息队列
头文件:sys/msg.h
原型: int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:msqid 为指定的消息队列标识符 msgp 为指向的用户定义缓冲区,
其结构如下:
struct msgbuf {
long mtype; //消息类型
char mtext[512]; //消息内容,使用时自己重新定义此结构
};
msgsz为发送信息的大小,其大小为 0到系统对消息队列的限制值。
msgflg用来指定在达到系统为消息队列所定的界限时应采取的操作。 可为以下值: IPC_NOWAIT:若消息队列已满(或者是队列中的消息总数等于系统限制值,或队列中的字节总数等于系统限制值),则指定IPC_NOWAIT使得msgsnd立即出错返回EAGAIN。如果没有指定IPC_NOWAIT ,则进程阻塞直到有空间可以容纳要发送的消息,或从系统中删除了此队列在成功调用后,将对消息队列 msqid 数据结构的成员执行下列操作: msg_qnum 以 1 为增量递增。 msg_lspid 设置为调用进程的进程 ID。 msg_stime 设置为当前时间。
返回值:成功返回0,失败返回-1
5.msgrcv--接收消息队列
头文件:sys/msg.h
原型:int msgrcv(int msqid,struct msgbuf *msgp,size_t msgsz,long int msgtyp,int msgflg);
参数:msqid:消息队列描述符。
msgp:读取的消息存储到msgp指向的消息结构中。
msgsz:消息缓冲区的大小。
msgtyp:为请求读取的消息类型。
msgflg:操作标志位。
msgflg可以为IPC_NOWAIT,IPC_EXCEPT,IPC_NOERROR: IPC_NOWAIT:如果没有满足条件的消息,调用立即返回 IPC_EXCEPT:与msgtyp配合使用,返回队列中第一个类型不为msgtyp的消息; IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将被丢弃。
返回值:成功会返回消息的实际字节数,否则返回-1
6.msgctl--消息队列属性控制
头文件: #include<sys/types.h>
#include<sys/msg.h>
#include<sys/ipc.h>
原型:int msgctl (int msqid, int cmd, struct msqid_ds *buf)
参数:
msqid 为消息队列标识符,
cmd 为执行的控制命令,可为: IPC_STAT:读取消息队列属性。 IPC_SET :设置消息队列属性。 IPC_RMID:删除消息队列。 IPC_INFO:读取消息队列基本情况 buf为msqid_ds 结构体类型的变量。用于存储读取的消息队列属性或者需要修改的消息队列属性
返回值:成功返回0,不成功返回-1
代码: (代码 有bug 那个 无用的字符数组 不要删 没有它,不能执行 )
/************************************************************************************************************************************************************************************************************************
*文件名:
*作 者:She001
*时 间:
*版 本:
*作 用:消息队列
****************************************************************************************************************************************************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>
#include<sys/wait.h>
#include<a.out.h>
#include<signal.h>
#include<stdarg.h>
#include<sys/socket.h>
#include<utime.h>
#include<sys/utsname.h>
#include<sys/times.h>
#include<sys/un.h>
#include<ctype.h>
#include<dirent.h>
#include<sys/time.h>
#include<sys/resource.h>
#include<syslog.h>
#include<pthread.h>
#include<semaphore.h>
#include<sys/time.h>
#include<sys/msg.h>
//ipcs -q 查看命令
//1.消息队列功能的使用测试
//2.创建一个消息队列
//2.向消息队列中写入数据
//3.从消息队列中读取数据
//销毁消息队列
struct msgbuf
{
long msgtype; //8个字节
char msgtext[512]; //字符串内容
};
int main()
{
//获取一个键值
key_t key = ftok(".",50);
if(key < 0)
{
perror("ftok error\n");
return -1;
}
printf("ftok is ok\n");
printf("key is : %d\n",key);
//获取一个消息队列
int msgid = msgget(key,IPC_CREAT | 0666);
if(msgid < 0)
{
perror("msgget is error\n");
return -1;
}
printf("msgid is : %d\n",msgid);
//向消息队列中添数据
struct msgbuf msgstr = {1,"hello linux"};
char *str = "hello linux";
int msgerr = msgsnd(msgid,&msgstr,sizeof(msgstr),IPC_NOWAIT);
if(msgerr <0)
{
perror("msgsnd error\n");
return -1;
}
struct msgbuf msgstr1 = {0};
char buff[128] = "";
int msglen = msgrcv(msgid,&msgstr1,sizeof(msgstr1),1,0);
printf("msgbuf is :%s msgtype is : %ld %d\n",msgstr1.msgtext,msgstr1.msgtype,msglen);
//删除消息队列
msgctl(msgid,IPC_RMID,NULL);
return 0 ;
}