linux应用编程笔记(15)消息队列编程
2015-12-09 17:38
761 查看
摘要: 总结了消息队列的定义,详解了使用消息队列的常用函数,最后给出一个实例加深理解。
一、什么是消息队列
由于linux早期的通信机制只有信号量,但是信号量所能够传递的数据量非常小,并且管道只能传送无格式的字节流,这样就越来越不能满足应用编程的需求,于是消息队列被开发出来克服了这些缺点。
消息队列本质是一个消息链表,可以把消息看做一个记录,其具有特定的格式,进程可以按照一定的规则向其中添加消息,另一些进程则可以根据规则读走这些消息。
消息队列有两个种类:一种是POSIX(可移植操作系统接口)消息队列,一种是system V消息队列,后者目前被大量的使用,其中系统V消息队列是随着内核持续的,只有在内核重启和人工删除的时候,该消息队列才会被删除。
二、使用消息队列的函数
1.创建键值函数
key_t ftok(char* fname,int id);
那么这个ftok是如何工作的呢?两个参数,一个是我们要使用的文件名,另一个是我们的项目id,一般id不要为0即可。ftok会根据这个两个数字组合成一个键值,当ab进程使用的时候根据文件名和项目id就会访问到相同的消息队列集合,这部分在前面信号量互斥编程的时候总结过,不多做赘述。
2.打开/创建消息队列
函数名:msgget
函数原型:int msgget(key_t key, int msgflg);
函数功能:获取消息队列的标识符
当key键值指定的信号量集合不存在,并且msgflg等于IPC_CREAT的时候,就创建消息队列,并和键值关联,返回与之对应的标识符。
头文件:#include <sys/types.h> #include<sys/ipc.h> #include <sys/msg.h>
返回值:成功返回与key对应的消息队列的标识符,失败返回-1
参数说明:
1.key_t key
由ftok获得,键值
2.int msgflg
标志位,主要有以下几个取值,IPC_CREAT,创建新的消息队列,IPC_EXCL,与IPC_CREAT一同使用,如果要创建的消息队列已经存在,则返回错误。IPC_NOWAIT读写消息队列无法满足的时候,不阻塞进程。
以下两种情况,将创建一个新的消息队列:第一,如果没有与key键值对应的消息队列,并且msgflg的值包含IPC_CREAT,就创建。第二,key的flg为IPC_PRIVATE。
3.发送消息
函数名:msgsnd
函数原型:int msgsnd(int msqid,const void *msgp,size_tmsgsz,int msgflg);
函数功能:向消息队列中发送一条消息。
头文件:#include <sys/types.h> #include<sys/ipc.h> #include <sys/msg.h>
返回值:成功返回0,失败返回-1。
参数说明:
1.int msqid
msgget函数返回的消息队列的标识符。
2.const void *msgp
该指针指向存放消息的结构体,具体结构如下:
struct msgbuf{
long mtype;//消息类型>0
char mtext[1];//消息数据的首地址
}
这里根据mtype的值来取啥名类型的消息,比如1对应一个类型,2对应一个类型,3对应一个类型等等。
3.size_t msgsz
消息数据的长度
4.int msgflg
发送标志,常用的就是IPC_NOWAIT,表示消息队列没有足够空间容纳发送的消息的时候,不阻塞发送消息的进程。
3.接受消息
函数名:msgrcv
函数原型:ssize_t msgsnd(int msqid, void *msgp,size_t msgsz,longmsgtyp,int msgflg);
函数功能:从msqid标识的消息队列中取走一条消息,该消息类型为msgtyp,并把消息存储在msgp指向的msgbuf中。在成功的读取一条消息后,该消息将在消息列表中被删除。
头文件:#include <sys/types.h> #include<sys/ipc.h> #include <sys/msg.h>
返回值:成功返回从数组中读取的消息的字节数,失败返回-1。
参数说明:
1.int msqid
msgget函数返回的消息队列的标识符。
2.void *msgp
该指针指向存放消息的结构体,具体结构如下:
struct msgbuf{
longmtype;//消息类型>0
char mtext[1];//消息数据的首地址
}
这里根据mtype的值来取啥名类型的消息,比如1对应一个类型,2对应一个类型,3对应一个类型等等。
3.size_t msgsz
消息数据的长度
4.long msgtyp
要取走的消息的类型
5.int msgflg
发送标志,常用的就是IPC_NOWAIT,表示消息队列没有足够空间容纳发送的消息的时候,不阻塞发送消息的进程。
下面是一个接受消息的例程:
4.删除消息队列
函数使用:msgctl(msgid,IPC_RMID,NULL);
返回值:失败返回-1则删除失败,成功返回0.
三、消息队列的使用编程
编译运行后效果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201908/15/b9a6e5c215c970812f6d408e48dbe24e)
这篇帖子就总结到这里,如有不正确地方还请指出,大家共同进步!
一、什么是消息队列
由于linux早期的通信机制只有信号量,但是信号量所能够传递的数据量非常小,并且管道只能传送无格式的字节流,这样就越来越不能满足应用编程的需求,于是消息队列被开发出来克服了这些缺点。
消息队列本质是一个消息链表,可以把消息看做一个记录,其具有特定的格式,进程可以按照一定的规则向其中添加消息,另一些进程则可以根据规则读走这些消息。
消息队列有两个种类:一种是POSIX(可移植操作系统接口)消息队列,一种是system V消息队列,后者目前被大量的使用,其中系统V消息队列是随着内核持续的,只有在内核重启和人工删除的时候,该消息队列才会被删除。
二、使用消息队列的函数
1.创建键值函数
key_t ftok(char* fname,int id);
那么这个ftok是如何工作的呢?两个参数,一个是我们要使用的文件名,另一个是我们的项目id,一般id不要为0即可。ftok会根据这个两个数字组合成一个键值,当ab进程使用的时候根据文件名和项目id就会访问到相同的消息队列集合,这部分在前面信号量互斥编程的时候总结过,不多做赘述。
2.打开/创建消息队列
函数名:msgget
函数原型:int msgget(key_t key, int msgflg);
函数功能:获取消息队列的标识符
当key键值指定的信号量集合不存在,并且msgflg等于IPC_CREAT的时候,就创建消息队列,并和键值关联,返回与之对应的标识符。
头文件:#include <sys/types.h> #include<sys/ipc.h> #include <sys/msg.h>
返回值:成功返回与key对应的消息队列的标识符,失败返回-1
参数说明:
1.key_t key
由ftok获得,键值
2.int msgflg
标志位,主要有以下几个取值,IPC_CREAT,创建新的消息队列,IPC_EXCL,与IPC_CREAT一同使用,如果要创建的消息队列已经存在,则返回错误。IPC_NOWAIT读写消息队列无法满足的时候,不阻塞进程。
以下两种情况,将创建一个新的消息队列:第一,如果没有与key键值对应的消息队列,并且msgflg的值包含IPC_CREAT,就创建。第二,key的flg为IPC_PRIVATE。
3.发送消息
函数名:msgsnd
函数原型:int msgsnd(int msqid,const void *msgp,size_tmsgsz,int msgflg);
函数功能:向消息队列中发送一条消息。
头文件:#include <sys/types.h> #include<sys/ipc.h> #include <sys/msg.h>
返回值:成功返回0,失败返回-1。
参数说明:
1.int msqid
msgget函数返回的消息队列的标识符。
2.const void *msgp
该指针指向存放消息的结构体,具体结构如下:
struct msgbuf{
long mtype;//消息类型>0
char mtext[1];//消息数据的首地址
}
这里根据mtype的值来取啥名类型的消息,比如1对应一个类型,2对应一个类型,3对应一个类型等等。
3.size_t msgsz
消息数据的长度
4.int msgflg
发送标志,常用的就是IPC_NOWAIT,表示消息队列没有足够空间容纳发送的消息的时候,不阻塞发送消息的进程。
3.接受消息
函数名:msgrcv
函数原型:ssize_t msgsnd(int msqid, void *msgp,size_t msgsz,longmsgtyp,int msgflg);
函数功能:从msqid标识的消息队列中取走一条消息,该消息类型为msgtyp,并把消息存储在msgp指向的msgbuf中。在成功的读取一条消息后,该消息将在消息列表中被删除。
头文件:#include <sys/types.h> #include<sys/ipc.h> #include <sys/msg.h>
返回值:成功返回从数组中读取的消息的字节数,失败返回-1。
参数说明:
1.int msqid
msgget函数返回的消息队列的标识符。
2.void *msgp
该指针指向存放消息的结构体,具体结构如下:
struct msgbuf{
longmtype;//消息类型>0
char mtext[1];//消息数据的首地址
}
这里根据mtype的值来取啥名类型的消息,比如1对应一个类型,2对应一个类型,3对应一个类型等等。
3.size_t msgsz
消息数据的长度
4.long msgtyp
要取走的消息的类型
5.int msgflg
发送标志,常用的就是IPC_NOWAIT,表示消息队列没有足够空间容纳发送的消息的时候,不阻塞发送消息的进程。
下面是一个接受消息的例程:
<span style="font-size:18px;">int read_message(int qid,long type,structmymsgbuf* qbuf) { int result,length; length=sizeof(structmymsgbuf)-sizeof(long); if((result==msgrcv(qid,qbuf,length,type,0))==-1) { return -1; } return result; } </span>
4.删除消息队列
函数使用:msgctl(msgid,IPC_RMID,NULL);
返回值:失败返回-1则删除失败,成功返回0.
三、消息队列的使用编程
<span style="font-size:18px;">#include <sys/ipc.h> #include <sys/msg.h> #include <sys/types.h> #include <stdio.h> #include <unistd.h> struct msg_buf//该机构体是存放消息类型和具体发送数据的 { int mtype; char data[255]; }; int main(void) { key_t key; int msgid; int ret; struct msg_buf msgbuf; /*创建键值*/ key=ftok("/home/passionbird/project",'p'); printf("key= %x\n",key); /*创建消息队列*/ msgid=msgget(key,IPC_CREAT|0666);//将创建的键值给msgget,如果不存在关联的消息队列,就创建,权限为0666 if(msgid == -1) { printf("creatmsg error!\n"); return-1; } /*发送消息到队列*/ msgbuf.mtype=getpid();//这里使用的消息类型由getpid()给出 strcpy(msgbuf.data,"thisis a msg test demo!");//将消息拷贝到msgbuf的data数组中 ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);//msgid是消息队列的标识符,第二个参数是指针,所以把结构体地址给进去, if(ret== -1) //第三个参数是数据的大小,最后是表示发送不了的时候不阻塞该进程。 { printf("sendmsg error!\n"); return-1; } /*从消息队列读走消息*/ ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT); if(ret== -1) { printf("receive msg error!\n"); return-1; } printf("We received message:%s\n",msgbuf.data);//打印出来接收到的消息 ret=msgctl(msgid,IPC_RMID,NULL);//删除消息队列 if(ret!= -1) { printf("remove mymsg sucessed!\n"); } return0; }</span>
编译运行后效果如下:
这篇帖子就总结到这里,如有不正确地方还请指出,大家共同进步!
相关文章推荐
- linux_安装_安装编译phantomjs 2.0的方法_转
- 20151209linux系统日常管理第四部分(系统服务管理;系统日志,xargs与exec)
- Linux特殊权限
- centos 5.9安装mysql5.7.9 +gcc编译升级
- linux 和 window 的EOF
- linux部署sh命令编写
- Centos | Linux 下安装启动 mysql 出现 8618 [ERROR] Aborting,查看日志:Plugin 'FEDERATED' is disabled.
- appcompat_v7 dont R linux ubuntu
- 管理SELINUX
- linux安装usb wifi接收器
- Linux脚本EOF
- lubuntu使用过的命令
- linux基础(七)----linux命令系统学习----系统安全相关命令
- linux基础(七)----linux命令系统学习----系统安全相关命令
- Linux学习笔记(二十一、输出重定向)
- linux中serial driver理解【转】
- errno.h linux errno
- Linux内核中进程上下文、中断上下文、原子上下文、用户上下文的理解【转】
- linux内核设计与实现笔记 进程调度
- linux下安装或升级GCC4.8,以支持C++11标准