进程间通信方式之消息队列
来源:互联网 发布:网络手游交易平台 编辑:程序博客网 时间:2024/05/29 18:01
消息队列进行通信的一些操作:
1、使用msgget()函数创建打开队列;
2、使用msgrcv()函数从队列中读数据;
3、使用msgsnd()函数写数据到队列中;
4、使用msgctl()函数控制消息队列。
以下是消息队列中使用到的一些函数:
1、msgget
功能:创建消息队列
头文件:#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
原型:int msgget(key_t key,int msgflg)
说明:key为键值,可设置成常数IPC_PRIVATE,或由ftok获取;
msgflg是标志位,设定的权限,
标志位如下:IPC_CREAT,创建新的队列;
IPC_EXCL,与IPC_CREAT一起使用,表示如果要创建的消息队列已经存在,则返 回错误;
IPC_NOWAIT,读写消息队列要求无法达到满足时,立即返回,不会出现堵塞
参数key虽然设置成常数IPC_PRVATE并不意味着其他进程不能访问该消息队列,只是意味着即将创 建新的消息队列。
返回值:成功返回消息队列描述字;
失败返回-1.
2、ftok
功能:将文件名转换成键值
头文件:#include <sys/types.h>
#include <sys/ipc.h>
原型:key_t ftok(char *pathname,char proj)
说明:pathname,路径名
proj,项目名,不为0即可
返回值:成功,返回与文件相对应的键值;
失败,返回-1.
3、msgsnd
功能:写数据到消息队列中
头文件:#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
原型:int msgsnd(int msqid,struct msgbuf *msgp,size_t msgz,int msgflg)
说明:msqid为消息队列ID,由内核反馈
struct msgbuf
{
long type; /* 消息类型,必须 > 0 */
char mtext[1]; /* 消息文本 */
};
msgsz:消息的大小。
返回值:成功返回0;失败返回-1,并将失败原因保存在errno中。
4、msgrcv
功能:读出消息队列的数据
头文件:#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
原型:int msgrcv(int msqid,struct msgbuf *msgp,int msgz,long msgtype,int msgflg)
说明:从msqid代表的消息队列中读取一个msgtype类型的消息,并把消息存储在msgp指定的msgbuf结构 中,在成功地读取了一条消息后将删除。
msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息。
msgtyp大于0,则返回其类型为mtype的第一个消息。
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。
msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。当消息从队列内取出后,相应的消息就从队列中删除了。
返回值:成功,返回实际读取的字节数;失败,返回-1。
5、msgctl
功能:控制消息队列
头文件:#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
原型:int msgctl(int msqid,int cmd,struct msqid_ds *buf)
说明:msgctl系统调用对msqid标识的消息队列执行cmd操作列。
队列的msqid_ds结构,对于每一个队列都有一个msqid_ds来描述队列当前的状态。结构定义如下:
struct msqid_ds {//Linux系统中的定义
struct ipc_perm msg_perm; /* Ownership and permissions
time_t msg_stime; /* Time of last msgsnd() */
time_t msg_rtime; /* Time of last msgrcv() */
time_t msg_ctime; /* Time of last change */
unsigned long __msg_cbytes; /* Current number of bytes inqueue (non-standard) */
msgqnum_t msg_qnum; /* Current number of messagesin queue */
msglen_t msg_qbytes; /* Maximum number of bytesallowed in queue */
pid_t msg_lspid; /* PID of last msgsnd() */
pid_t msg_lrpid; /* PID of last msgrcv() */
};//不同的系统中此结构会有不同的新成员
cmd:IPC_STAT,读取消息队列的数据结构msqid_ds,并将其存储在b u f指定的地址中。
IPC_SET,设置消息队列的数据结构msqid_ds中的ipc_perm元素的值。这个值取自buf参数。
IPC_RMID,从系统内核中移走消息队列。
返回值:成功返回0;失败返回-1,并将错误原因保存在errno中,errno = EACCES (没有读的权限同时 cmd 是IPC_STAT )
EFAULT (buf 指向的地址无效)
EIDRM (在读取中队列被删除)
EINVAL (msgqid无效, 或者msgsz 小于0 )
EPERM (IPC_SET或者IPC_RMID 命令被使用,但调用程序没有写的权限)
以下是两个队列之间通信的代码:
msg1.c:
#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>struct my_msg_st{ long int my_msg_type; char some_text[BUFSIZ];};int main(){ int running = 1; int msgid; struct my_msg_st some_data; long int msg_to_receive = 0; /*创建消息队列*/ msgid = msgget((key_t)1234,0666 | IPC_CREAT); if(-1 == msgid) { fprintf(stderr,"msgget failed with error:%d\n",errno); exit(EXIT_FAILURE); } /*循环从消息队列中接收消息*/ while(running) { /*读取消息*/ if(-1 == msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)) { fprintf(stderr,"msgrcv failed with error:%d\n",errno); exit(EXIT_FAILURE); } printf("You wrote:%s",some_data.some_text); /*接收到消息为“end”时结束循环*/ if(0 == strncmp(some_data.some_text,"end",3)) { running = 0; } } /*从系统内核中移走消息队列*/ if(-1 == msgctl(msgid,IPC_RMID,0)) { fprintf(stderr,"msgctl(IPC_RMID) failed!\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS);}
msg2.c:
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#define MAX_TEXT 512struct my_msg_st{ long int my_msg_type; char some_text[MAX_TEXT];};int main(){ int running = 1; struct my_msg_st some_data; int msgid; char buffer[BUFSIZ]; /*创建消息队列*/ msgid = msgget((key_t)1234,0666 | IPC_CREAT); if(-1 == msgid) { fprintf(stderr,"msgget failed with error:%d!\n",errno); exit(EXIT_FAILURE); } /*循环向消息队列中添加消息*/ while(running) { printf("Enter some text:"); fgets(buffer,BUFSIZ,stdin); some_data.my_msg_type = 1; strcpy(some_data.some_text,buffer); /*添加消息*/ if(-1 == msgsnd(msgid,(void *)&some_data,MAX_TEXT,0)) { fprintf(stderr,"msgsnd failed!\n"); exit(EXIT_FAILURE); } /*用户输入的为“end”时结束循环*/ if(0 == strncmp(buffer,"end",3)) { running = 0; } } exit(EXIT_SUCCESS);}
调试结果:
./msg1
You wrote:2You wrote:dssYou wrote:end./msg2
Enter some text:2Enter some text:dssEnter some text:end
- 进程间通信方式之消息队列
- 进程间通信:消息队列通信方式
- 进程间通信方式之(五)消息队列
- Linux进程间通信方式之消息队列
- python进阶之进程间通信方式之一消息队列
- 进程间通信之消息队列通信
- 【进程间通信方式二】消息队列
- msgget();msgsnd();msgrcv();msgctl(); 消息队列 Linux进程间的通信方式之消息队列
- linux进程间通信之消息队列
- 进程间通信之消息队列篇
- linux进程间通信之消息队列
- 进程间通信之消息队列
- linux进程间通信之消息队列
- Linux进程间通信之消息队列
- 进程间通信之消息队列
- 进程间通信之消息队列
- 进程间的通信之消息队列
- 进程间通信之消息队列
- 安卓的体系
- Android中使用Handler造成内存泄露的分析和解决
- POJ 3184 DP+剪枝
- 深入理解python递归函数:汉诺塔游戏
- java基础2
- 进程间通信方式之消息队列
- PPT的基本制作
- 1103 Java-Scanner的使用
- 5.ubuntu下tomcat起不起来以及一些小问题
- Android 实现类似美团的菜单效果
- JS组件系列——封装自己的JS组件
- select for update
- 如何将小视频转换成GIF动图或将GIF动图转换成视频
- 有一个理财管理数据库,包括客户Client,资金账户Fund,经理人Manager,投资流水Investment,理财产品Product。(转)