linux IPC 通信 study 四:SYSTEM_V消息队列
linux 消息队列 分为两个标准,分别为SystemV消息队列,POSIX消息队列
SystemV消息队列 几个API的解释 1,ftok sys/ipc.h key_t ftok(const char *path, int id); 该函数根据制定的路径和id,产生一个Key给msgq,sem,shm使用,path必须是一个可以访问的文件名,id只有低8位有用,但是id到底能不能等0,这个有疑问,从使用上来讲,可以等0,但是看手册里的解释,是个非零值. 在使用该函数的过程中要确保path不能被删除然后再重新创建,这回导致key值变化,产生意想不到的结果,其实也可以约定好一个整数值作为key。
http://blog.csdn.net/u013485792/article/details/50764224 链接中的解释更详细一点。
2,msgget sys/msg.h int msgget(key_t key, int flag); 创建或者打开一个已经存在的消息队列,成功时返回msgid,失败是-1,errno可以判断失败的原因。 参数key:IPC_PRIVATE,创建一个只能被创建进程读写的消息队列, 可以是一个约定好的数值 可以使用ftok获得。 参数flag: IPC_CREAT如果消息队列存在就返回,如果不存在就创建一个新的。 IPC_EXCL如果消息队列存在,就出错,如果不存在就正常创建,这样可以保证产生的是一个新的消息队列。消息的定义 struct mymsg { long mtype; /*消息类型positive message type*/ char mtext[1];/*message data, of length nbytes,真正的消息长度,nbytes参数的值*/ };3,msgsnd 向消息队列中发送一个消息 sys/msg.h int msgsnd(int msgid, const void *ptr, size_t nbytes, int flag); 成功返回0,失败返回-1,errno标识错误类型 参数msgid是msgget的返回值。 参数ptr指向消息的指针。 参数nbytes是实际的消息长度,并不包括mtype的长度。 参数flag, IPC_NOWAIT表示以非阻塞的方式发送消息,如果消息队列已经满了,立即出错返回EAGAIN,如果不制定就会阻塞在这里直到消息成功发送4,msgrcv 从消息队列中取出消息 sys/msg.h size_t msgrcv(int msgid, void *ptr, size_t nbytes, long type, int flag); 函数执行成功,返回消息数据部分的长度,若出错返回-1 参数msgid是通过msgget获得的。 参数ptr指向存储读出来消息的存储空间 参数nbytes标识消息部分的长度,不包括mtype的长度 参数type表示想要哪一种消息,0表示返回队列中的第一个消息, 正数,表示返回正数类型的消息的第一个消息,负数,表示返回消息类型小于等于abs(type)的消息,如果这种消息有若干个,则取消息类型最小的那个。 参数flag, IPC_NOWAIT同样表示阻塞非阻塞5,msgctl 对消息队列进行处理,类似于ioctl函数 sys/msg.h int msgctl(int msgid, int cmd, struct msgid_ds *buf); 成功返回0,失败返回-1, errno指示错误类型 参数msgid是通过msgget获得的 参数cmd: IPC_STAT获取消息队列的msgid_ds结构 IPC_SET 设置相关信息 IPC_RMID 删除消息队列,注意system v并没有msgclose这样的函数 提供一个会话程序server部分
/*************************************************************************> File Name: svr.c> Author: ma6174> Mail: ma6174@163.com > Created Time: 2016年12月23日 星期五 13时55分00秒************************************************************************/#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>#define MSGQ "/"
#define MSGQ_RES "/home"
#define MSG_SIZE 512
struct mymsg {long mtype;unsigned char msg_buf[MSG_SIZE];
};int server_msgsnd(int msgq, void *data, int size, int flag)
{int ret = 0;while (1) {ret = msgsnd(msgq, data, size, flag);if (ret >= 0)return ret;else {/*printf("server send msg :%s\n", strerror(errno));if (errno == ENOMSG || errno == EAGAIN) {if (errno == ENOMSG)printf("server send : NO MSG \n");if (errno == EAGAIN)printf("server send : MSG AGAIN\n");}sleep(1);continue;*/}}return ret;
}int server_msgrcv(int msgq, void *data, int size, int request, int flag)
{int ret = 0;while (1) {ret = msgrcv(msgq, data, size, request, flag);if (ret >= 0) {return ret;} else {if (errno == EIDRM) {printf("server:msg queue was rm by client\n");exit(1);}/*printf("server send msg %s\n", strerror(errno));if (errno == ENOMSG || errno == EAGAIN) {if (errno == ENOMSG)printf("server recv : NO MSG \n");if (errno == EAGAIN)printf("server recv : MSG AGAIN\n");}sleep(1);continue;*/}}return ret;
}int main(int argc, char **argv)
{/* * 1 ftok get key or use a fixed num* 2 msgget open or create a message queue* 3 msgsnd msgrcv send or receive info* 4 msgctl close message queue* */key_t key;int ret = 0;int proj_id = 0x01;key = ftok(MSGQ, proj_id);int msgq = msgget(key, IPC_CREAT | S_IRWXU | S_IRWXG | S_IRWXO);if (msgq < 0) {printf("create msg queue failed\n");return -1;}int msgq_res = msgget(0x25, IPC_CREAT | S_IRWXU | S_IRWXG | S_IRWXO);struct mymsg rcv_msg_data, snd_msg_data;while (1) {memset(&rcv_msg_data, 0, sizeof(struct mymsg));memset(&snd_msg_data, 0, sizeof(struct mymsg));//ret = server_msgrcv(msgq, &rcv_msg_data, sizeof(struct mymsg), 0, IPC_NOWAIT);ret = server_msgrcv(msgq, &rcv_msg_data, MSG_SIZE, 0, IPC_NOWAIT);if (ret >= 0) {printf("server recv msg ok len = %d\n", ret);} else {if (errno == EIDRM) {printf("server:msg queue was rm by client\n");exit(1);}}if (rcv_msg_data.mtype == 1) {snd_msg_data.mtype = rcv_msg_data.mtype;printf("server: msg request 1\n");strcpy(snd_msg_data.msg_buf, "you request msg type 1");} else if (rcv_msg_data.mtype == 2) {snd_msg_data.mtype = rcv_msg_data.mtype;printf("server: msg request 2\n");strcpy(snd_msg_data.msg_buf, "you request msg type 2");} else if (rcv_msg_data.mtype == 3) {snd_msg_data.mtype = rcv_msg_data.mtype;printf("server: msg request 3\n");strcpy(snd_msg_data.msg_buf, "you request msg type 3");}//ret = server_msgsnd(msgq, &snd_msg_data, sizeof(struct mymsg), IPC_NOWAIT);ret = server_msgsnd(msgq_res, &snd_msg_data, MSG_SIZE, IPC_NOWAIT);if (ret >= 0) {printf("server send msg ok len = %d\n", ret);} else {printf("server: send msg failed\n");}usleep(10);}return ret;
}
client部分
/*************************************************************************> File Name: svr.c> Author: ma6174> Mail: ma6174@163.com > Created Time: 2016年12月23日 星期五 13时55分00秒************************************************************************/#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>#define MSGQ "/"
#define MSG_SIZE (512)struct mymsg {long mtype;unsigned char msg_buf[512];
};int client_send(int msgq, void *data, int size, int flag)
{int ret = 0;while (1) {ret = msgsnd(msgq, data, size, flag);if (0 == ret)return ret;else if (ret < 0) {/*if (errno == ENOMSG || errno == EAGAIN) {if (errno == ENOMSG)printf("client send:NO MSG \n");if (errno == EAGAIN)printf("client send: MSG AGAIN\n");}*/continue;}}return ret;
}int client_msgrcv(int msgq, void *data, int size, int request, int flag)
{int ret = 0;while (1) {ret = msgrcv(msgq, data, size, request, flag);if (ret >= 0)return ret;if (ret < 0) {/*if (errno == ENOMSG || errno == EAGAIN) {if (errno == ENOMSG)printf("client recv : NO MSG \n");if (errno == EAGAIN)printf("client recv : MSG AGAIN\n");}*/continue;}}return ret;}
int main(int argc, char **argv)
{int ret = 0;key_t key;int proj_id = 0x01;key = ftok(MSGQ, proj_id);int msgq = msgget(key, IPC_CREAT | S_IRWXU | S_IRWXG | S_IRWXO);if (msgq < 0) {printf("create msg queue failed\n");return -1;}int msgq_res = msgget(0x25, IPC_CREAT | S_IRWXU | S_IRWXG | S_IRWXO);struct mymsg rcv_msg_data, snd_msg_data;int idx = 1;while (idx < 4) {memset(&rcv_msg_data, 0, sizeof(struct mymsg));memset(&snd_msg_data, 0, sizeof(struct mymsg));snd_msg_data.mtype = idx;//ret = client_send(msgq, &snd_msg_data, sizeof(struct mymsg), IPC_NOWAIT);ret = client_send(msgq, &snd_msg_data, MSG_SIZE, IPC_NOWAIT);if (ret < 0)printf("client send msg fail\n");else if (0 == ret)printf("\tclient send type %d\n", idx);ret = client_msgrcv(msgq_res, &rcv_msg_data, MSG_SIZE,rcv_msg_data.mtype, IPC_NOWAIT);if (ret < 0) {printf("\tclient receive msg failed\n");} else printf("\t\tclient get : len = %d, type = %ld, %s\n", ret, rcv_msg_data.mtype, rcv_msg_data.msg_buf);idx++;usleep(50);}sleep(10);/*client close msg queue, in fact, client cannot remove msgq*/ret = msgctl(msgq, IPC_RMID, NULL);ret = msgctl(msgq_res, IPC_RMID, NULL);printf("client exit and rm msg queue\n");return ret;
}
执行效果如图:
linux IPC 通信 study 四:SYSTEM_V消息队列相关推荐
- Linux进程通信之System V消息队列
System V消息队列是Open Group定义的XSI,不属于POSIX标准.System V IPC的历史相对很早,在上个世70年代后期有贝尔实验室的分支机构开发,80年代加入System V的 ...
- Linux IPC实践(6) --System V消息队列(3)
消息队列综合案例 消息队列实现回射客户/服务器 server进程接收时, 指定msgtyp为0, 从队首不断接收消息 server进程发送时, 将mtype指定为接收到的client进程的pid cl ...
- Linux IPC实践(4) --System V消息队列(1)
消息队列概述 消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法(仅局限于本机); 每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值. 消息队列也有管道一样的不足: ...
- Linux IPC实践(5) --System V消息队列(2)
消息发送/接收API msgsnd函数 int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg); 参数 msgid: 由ms ...
- Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结
Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...
- Linux系统编程(七)消息队列
Linux系统编程(七)消息队列 一.什么是消息队列 二.消息队列内部原理 三.实现消息队列的收发 1.发送消息队列 2.接收消息队列 四.消息队列与命名管道的比较 一.什么是消息队列 消息队列提供了 ...
- linux网络编程之System V 消息队列(一):消息队列内核结构和msgget、msgctl 函数
一.消息队列 1.消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法 2.每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值 3.消息队列与管道不同的是,消息队列是基于 ...
- Linux进程间通信四 Posix 消息队列简介与示例
目录 1. Posix 消息队列简介 2. API接口 2.1 创建或打开消息队列 2.2 发送消息 2.3 接收消息 2.4 获取.设置消息队列属性 2.5 关闭消息队列 2.6 删除消息队列 2. ...
- 【Linux系统编程】进程间通信之消息队列
00. 目录 文章目录 00. 目录 01. 消息队列概述 02. 消息队列相关函数 03. 消息队列读写操作 04. 测试代码 05. 附录 01. 消息队列概述 消息队列提供了一种在两个不相关的进 ...
最新文章
- 找到一本不错的Linux电子书,附《Linux就该这么学》章节目录
- 会计基础第一章模拟试题(1)
- 最简单的matplotlib写法
- 性能监控—spotlight监控mysql性能
- ios笔试题算法_iOS 算法面试题(一)
- python继承方式是基于原型吗_[译] 为什么原型继承很重要
- Mysql_mysql多个TimeStamp设置
- 51nod 1062 序列中最大的数【打表】
- 在win7的操作系统下安装Oracle11R2
- cas 单点登录_CAS 单点登录简介
- java微信h5支付_Java-实现微信H5支付
- Git查看本地配置信息
- U-BLOX GPS 模块及GPRMC指令解析
- 移动用户体验设计:iOS APP体验设计
- 前端使用 CryptoJS(v3.1.2) 进行des解密,后端java
- Centos7初始化网络配置
- matlab 距平,MATLAB及其在地学中地应用.PDF
- 【软件工程】软件与软件危机
- 如何下载宁河区卫星地图高清版大图
- stm32 移植java_把Lua移植到stm32上,效果不错! (amoBBS 阿莫电子论坛)