linux IPC 通信 study 四:SYSTEM_V消息队列
2015-11-03 17:45
567 查看
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(i 4000 nt 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_系统破坏性修复实验
- linux IPC 通信 study 三:system v 信号量semphore
- linux IPC 通信 study 二:信号signal
- RHEL/CentOS 7.x/6.x/5.x EPEL Repository
- linux IPC 通信 study 一:管道
- linux下rarlinux安装后找不到rar命令处理方法
- centos编译安装svn
- linux网卡统计信息清零
- centos 新增用户, 然后他在主目录添加网站403Forbbiden
- Linux C中读取/dev/input/event设备来判断键盘按键是否按下
- linux线程异常保护
- linux一天一命令博客链接
- linux下静态库的ranlib使用
- linux ar命令用法
- linux的crontab定时服务备份mysql数据
- Centos7 安装python3的独立环境
- Linux下使用Eclipse开发Hadoop应用程序
- Linux下crontab定时执行脚本
- java代码调用linux命令,生成.pem公钥私钥证书
- centos7 挂载virtualbox 中无法挂载共享文件