Linux:进程通信之消息队列Message实例
/*send.c*/
/*send.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h> #define MSGKEY 1024 struct msgstru
{
long msgtype;
char msgtext[2048];
}; main()
{
struct msgstru msgs;
int msg_type;
char str[256];
int ret_value;
int msqid; msqid=msgget(MSGKEY,IPC_EXCL); /*检查消息队列是否存在*/
printf("msqid:%d \n",msqid);
if(msqid < 0){
msqid = msgget(MSGKEY,IPC_CREAT|0666);/*创建消息队列*/
printf("msqid:%d \n",msqid);
if(msqid <0){
printf("failed to create msq | errno=%d [%s]\n",errno,strerror(errno));
exit(-1);
}
} while (1){
printf("input message type(end:0):");
scanf("%d",&msg_type);
if (msg_type == 0)
break;
printf("input message to be sent:");
scanf ("%s",str);
msgs.msgtype = msg_type;
strcpy(msgs.msgtext, str);
/* 发送消息队列 */
printf("msqid:%d,msgs.msgtext: %s,size:%d\n",msqid,msgs.msgtext,sizeof(msgs.msgtext));
ret_value = msgsnd(msqid,&msgs,sizeof(struct msgstru),IPC_NOWAIT);
printf("sendXxdl(),ret_value:%d,sizeof(struct msgstru):%d \n",ret_value,sizeof(struct msgstru));
if ( ret_value < 0 ) {
printf("msgsnd() write msg failed,errno=%d[%s]\n",errno,strerror(errno));
exit(-1);
}
}
msgctl(msqid,IPC_RMID,0); //删除消息队列
}
/*receive.c */
/*receive.c */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h> #define MSGKEY 1024 struct msgstru
{
long msgtype;
char msgtext[2048];
}; /*子进程,监听消息队列*/
void childproc(){
struct msgstru msgs;
int msgid,ret_value;
char str[512]; while(1){
msgid = msgget(MSGKEY,IPC_EXCL );/*检查消息队列是否存在 */
if(msgid < 0){
printf("msq not existed! errno=%d [%s]\n",errno,strerror(errno));
sleep(2);
continue;
}
/*接收消息队列*/
ret_value = msgrcv(msgid,&msgs,sizeof(struct msgstru),0,0);
printf("text=[%s] pid=[%d]\n",msgs.msgtext,getpid());
}
return;
} void main()
{
int i,cpid;
printf("open receive\n");
/* create 5 child process */
for (i=0;i<1;i++){
cpid = fork();
if (cpid < 0)
printf("fork failed\n");
else if (cpid ==0) /*child process*/
childproc();
}
}
实现linux进程通信的方式有5种:
--信号(Singal)
--管道(Pipe)
--消息队列(Message)
--信号量(Semaphore)
消息队列
一、概念
消息队列就是一个消息的链表。可以把消息看作一个记录,具有特定的格式以及特定的优先级。对消息队列有写权限的进程可以向中按照一定的规则添加新消息;有读权限的进程则可以读走消息。读走就没有了。消息队列是随内核持续的。 只有内核重启或人工删除时,该消息才会被删除。在系统范围内,消息队列与键值唯一对应。
消息队列的数据结构
1.struct msqid_ds *msgque[MSGMNI]向量:
msgque[MSGMNI]是一个msqid_ds结构的指针数组,每个msqid_ds结构指针代表一个系统消息队列,msgque[MSGMNI]的大小为MSGMNI=128,也就是说系统最多有MSGMNI=128个消息队列
2.struct msqid_ds
一个消息队列结构
struct msqid_ds 中主要数据成员介绍如下:
struct msqid_ds
{
struct ipc_perm msg_perm;
struct msg *msg_first; /*消息队列头指针*/
struct msg *msg_last; /*消息队列尾指针*/
__kernel_time_t msg_stime; /*最后一次插入消息队列消息的时间*/
__kernel_time_t msg_rtime; /*最后一次接收消息即删除队列中一个消息的时间*/
__kernel_time_t msg_ctime;
struct wait_queue *wwait; /*发送消息等待进程队列*/
struct wait_queue *rwait;
unsigned short msg_cbytes;
unsigned short msg_qnum; /*消息队列中的消息个数*/
unsigned short msg_qbytes;
__kernel_ipc_pid_t msg_lspid; /*最后一次消息发送进程的pid*/
__kernel_ipc_pid_t msg_lrpid; /*最后一次消息发送进程的pid*/
};
3.struct msg 消息节点结构:
msqid_ds.msg_first,msg_last维护的链表队列中的一个链表节点
struct msg
{
msg *msg_next; /*下一个msg*/
long msg_type; /*消息类型*/
*msg_spot; /*消息体开始位置指针*/
msg_ts; /*消息体长度*/
message; /*消息体*/
}
4.msgbuf消息内容结构:
msg 消息节点中的消息体,也是消息队列使用进程(消息队列发送接收进程)发送或者接收的消息
struct msgbuf
{
long mtype; --消息类型
char mtext[n]; --消息内容
}
二、步骤及思路
1、取得键值
2、打开、创建消息队列
3、发送消息
4、接收消息
下面具体看看:
1、取得键值
key_t ftok(char *pathname, char proj)
头文件为<sys/ipc.h>。返回文件名对应的键值,失败返回 -1。proj是项目名,随便写,不为0就行。
fname就是你指定的文件名(已经存在的文件名)。需要有-t 的权限,或用root权限执行,通常设为/tmp或设为" . "。这里我感觉不用这个函数也行,因为key值可以自己指定,例如: #define KEY_MSG 0x101
2、打开、创建消息队列
int msgget(key_t key, int msgflg)
头文件为<sys/msg.h>。key由ftok获得。
msgflg有:
IPC_CREAT 创建新的消息队列,应配有文件权限0666。
IPC_EXCL 与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。
IPC_NOWAIT 读写消息不阻塞。
当没有与key相对应的消息队列并且msgflg中包含了IPC_CREAT标志 或 key的参数为IPC_PRIVATE 时,创建一个新的消息队列。
3、发送消息
int msgsnd(int msqid, struct msgbuf *msgp, int msgsz, int msgflg)
向消息队列发送一条消息。msqid为消息队列的id,msgp为存放消息的结构体。msgsz是消息的长度,和数组的大小不一样哦。msgflg为消息标志,通常为0,也可以为IPC_NOWAIT。出错返回 -1。
消息格式
struct msgbuf {
long mtype;
char mtext[100];
};
4、接收消息
int msgrcv(int msqid, struct msgbuf *msgp, int msgsz, long msgtyp, int msgflg)
从msqid代表的消息队列中读取一个msgtyp类型的消息,并把消息存储在msgp指定的msgbuf结构中。读取后队列中的消息将会删除。size为结构体中数据的大小,不要计算msgtyp。出错返回 -1。
Linux:进程通信之消息队列Message实例的更多相关文章
- linux进程通信:消息队列
消息队列可以实现两个没有关系的进程之间的通信. 创建了一个消息队列后,进程可以往里面放消息,也可以取消息.因为这个消息队列是有名字的,所以就算是两个没有关系的进程,也能通信. 而且人性化的一点是,可以 ...
- linux 进程学习笔记-消息队列messagequeue
可以想象,如果两个进程都可以访问同一个队列:其中一个进程(sender)向其中写入结构化数据,另外一个进程(receiver)再从其中把结构化的数据读取出来.那么这两个进程就是在利用这个队列进行通信了 ...
- [转]Linux进程通信之POSIX消息队列
进程间的消息队列可以用这个实现,学习了下. http://blog.csdn.net/anonymalias/article/details/9799645?utm_source=tuicool&am ...
- linux消息队列编程实例
转自:linux 消息队列实例 前言: 消息队列就是一个消息的链表.可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向其中按照一定的规则添加新消息:对消息队列有读权 ...
- Linux 进程间通信(posix消息队列 简单)实例
Linux 进程间通信(posix消息队列 简单)实例 详情见: http://www.linuxidc.com/Linux/2011-10/44828.htm 编译: gcc -o consumer ...
- Linux进程间通信(System V) --- 消息队列
消息队列 IPC 原理 消息队列是消息的链式队列,如下图为消息队列的模型.整个消息队列有两种类型的数据结构. 1.msqid_ds 消息队列数据结构:描述整个消息队列的属性,主要包括整个消息队列的权限 ...
- linux进程通信
e14: 进程间通信(进程之间发送/接收字符串/结构体): 传统的通信方式: 管道(有名管道 fifo,无名管道 pipe) 信号 signal System V(基于IPC的对象): ...
- IPC通信:Posix消息队列
IPC通信:Posix消息队列 消息队列可以认为是一个链表.进程(线程)可以往里写消息,也可以从里面取出消息.一个进程可以往某个消息队列里写消息,然后终止,另一个进程随时可以从消息队列里取走这些消息. ...
- Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字
Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...
随机推荐
- J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用
J2EE进阶(十六)Hibernate 中getHibernateTemplate()方法使用 spring 中获得由spring所配置的hibernate的操作对象,然后利用此对象进行,保存,修 ...
- OpenMP实现生产者消费者模型
生产者消费者模型已经很古老了吧,最近写了个OpenMP版的此模型之实现,来分享下. 先说一下模型的大致做法是: 1.生产者需要取任务,生产产品. 2.消费者需要取产品,消费产品. 生产者在生产某个产品 ...
- activiti 多实例任务
1.1.1. 前言 个人,那么当5个人都投票的时候大概分为如下几种: 1.部门所有人都去投票,当所有人都投票完成的时候,这个节点结束,流程运转到下一个节点.(所有的人都需要投票) 2.部门所有人都去投 ...
- ISP(Interface Segregation Principle),接口隔离原则
ISP(Interface Segregation Principle),接口隔离原则 它要求如下: ① 一个类对另一个类的依赖性要建立在最小接口上. ② 使用多个专门的接口比使用单一的总接口要好 ...
- 自制 Python小工具 将markdown文件转换成Html文件
今天看到了一个Python库,名为markdown.瞬间就给了我一个灵感,那就是制作一个将markdown文件转换成html文件的小工具. 我的实验环境 操作系统: Windows 7 64位 旗舰版 ...
- Socket实现单客户端与服务器对话功能
单客户端,顾名思义,就是客户端只有一个用户去访问服务器,然后服务器根据该客户请求返回信息,先看下效果图: 服务端(左)和客户端(右): 注意,我是用了两个eclipse,一个只放服务端文件,一个只放客 ...
- [代码应用]javaSE程序递归删除文件夹下的.bak文件程序源代码
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39158939 本文作者:sushengmiyan ------------------ ...
- Android必知必会-使用okhttp的PUT方式上传文件
注:如果移动端排版有问题,请看 简书版 (<-点击左边),希望CSDN能更好的支持移动端. 背景 公司的文件上传接口使用PUT协议,之前一直用的都是老项目中的上传类,现在项目中使用了okhttp ...
- MacOS的菜单状态栏App添加饼型进度
猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/52075418 ...
- 深入理解Express.js
转自:http://xvfeng.me/posts/understanding-expressjs/ 英文原文更赞:http://evanhahn.com/understanding-express- ...