详解linux进程间通信-消息队列

前言:前面讨论了信号、管道的进程间通信方式,接下来将讨论消息队列。

  一、系统V IPC

  三种系统V IPC:消息队列、信号量以及共享内存(共享存储器)之间有很多相似之处。

  每个内核中的 I P C结构(消息队列、信号量或共享存储段)都用一个非负整数的标识符
( i d e n t i f i e r )加以引用。

  无论何时创建I P C结构(调用m s g g e t、 s e m g e t或s h m g e t) ,都应指定一个关键字(k e y),关
键字的数据类型由系统规定为 k e y _ t,通常在头文件< s y s / t y p e s . h >中被规定为长整型。关键字由
内核变换成标识符。

  以上简单介绍了IPC,对接下来介绍的消息队列、信号量和共享内存有助于理解。

  二、消息队列

  1、简介

  消息队列是消息的链接表 ,存放在内核中并由消息队列标识符标识。我们将称消息队列为 
“队列”,其标识符为“队列 I D”。 m s g g e t用于创建一个新队列或打开一个现存的队列。 m s g s n d
用于将新消息添加到队列尾端。每个消息包含一个正长整型类型字段,一个非负长度以及实际
数据字节(对应于长度),所有这些都在将消息添加到队列时,传送给 m s g s n d。 m s g r c v用于从
队列中取消息。我们并不一定要以先进先出次序取消息,也可以按消息的类型字段取消息。

  2、函数介绍

  • ftok函数

#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);//“/home/linux” , 'a'
功能:生成一个key(键值)

  • msgget函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

功能:创建或取得一个消息队列对象
返回:消息队列对象的id 同一个key得到同一个对象
格式:msgget(key,flag|mode);
flag:可以是0或者IPC_CREAT(不存在就创建) 
mode:同文件权限一样

  • msgsnd函数

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:将msgp消息写入标识为msgid的消息队列
msgp: 
struct msgbuf {
long mtype; /* message type, must be > 0 */消息的类型必须>0
char mtext[1]; /* message data */长度随意
};

msgsz:要发送的消息的大小 不包括消息的类型占用的4个字节
msgflg: 如果是0 当消息队列为满 msgsnd会阻塞
如果是IPC_NOWAIT 当消息队列为满时 不阻塞 立即返回

返回值:成功返回id 失败返回-1

  • msgrcv函数

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
int msgflg);

功能:从标识符为msgid的消息队列里接收一个指定类型的消息 并 存储于msgp中 读取后 把消息从消息队列中删除
msgtyp:为 0 表示无论什么类型 都可以接收
msgp:存放消息的结构体
msgsz:要接收的消息的大小 不包含消息类型占用的4字节
msgflg:如果是0 标识如果没有指定类型的消息 就一直等待
如果是IPC_NOWAIT 则表示不等待

  • msgctl函数

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
msgctl(msgid,IPC_RMID,NULL);//删除消息队列对象

  程序2-2将简单演示消息队列:

  ---  snd.c  ---

#include "my.h"typedef struct{long type;char name[20];int age;
}Msg;int main()
{key_t key = ftok("/home/liudw",'6');printf("key:%x\n",key);int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);if(msgid<0){   perror("msgget error!");exit(-1);}   Msg m;puts("please input your type name age:");scanf("%ld%s%d",&m.type,m.name,&m.age);msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);return 0;
}

  ---  rcv.c  ---

#include "my.h"typedef struct{long type;char name[20];int age;
}Msg;int main()
{key_t key = ftok("/home/liudw",'6');printf("key:%x\n",key);int msgid = msgget(key,O_RDONLY);if(msgid<0){   perror("msgget error!");exit(-1);}   Msg rcv;long type;puts("please input type you want!");scanf("%ld",&type);msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);msgctl(msgid,IPC_RMID,NULL);return 0;
}

  运行演示:

  三、详解ftok函数 

  • ftok根据路径名,提取文件信息,再根据这些文件信息及project ID合成key,该路径可以随便设置。
  • 该路径是必须存在的,ftok只是根据文件inode在系统内的唯一性来取一个数值,和文件的权限无关。
  • proj_id是可以根据自己的约定,随意设置。这个数字,有的称之为project ID; 在UNIX系统上,它的取值是1到255;

  为了验证以上观点,对程序2-2稍作修改,将路径和proj_id修改:

  程序3-1如下:

  ---  snd.c  ---

#include "my.h"typedef struct{long type;char name[20];int age;
}Msg;int main()
{key_t key = ftok("/home",'a');printf("key:%x\n",key);int msgid = msgget(key,IPC_CREAT|O_WRONLY|0777);if(msgid<0){   perror("msgget error!");exit(-1);}   Msg m;puts("please input your type name age:");scanf("%ld%s%d",&m.type,m.name,&m.age);msgsnd(msgid,&m,sizeof(m)-sizeof(m.type),0);return 0;
}

  ---  rcv.c  ---

#include "my.h"typedef struct{long type;char name[20];int age;
}Msg;int main()
{key_t key = ftok("/home",'a');printf("key:%x\n",key);int msgid = msgget(key,O_RDONLY);if(msgid<0){   perror("msgget error!");exit(-1);}   Msg rcv;long type;puts("please input type you want!");scanf("%ld",&type);msgrcv(msgid,&rcv,sizeof(rcv)-sizeof(type),type,0);printf("rcv--name:%s age:%d\n",rcv.name,rcv.age);msgctl(msgid,IPC_RMID,NULL);return 0;
}

  运行演示如下图:

 

linux 进程通信 消息队列相关推荐

  1. Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结

    Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...

  2. Linux进程通信之消息队列

    目录 1.消息队列的原理: 2.消息队列的接口: (1)创建消息队列 (2)向消息队列发送消息 (3)接收消息 (4)操作消息队列的接口 1.消息队列的原理: 消息队列(messagequeue)以链 ...

  3. ZUCC_操作系统原理实验_Lab9进程的通信消息队列

    lab9进程的通信–消息队列 一.两个进程并发执行,通过消息队列,分别进行消息的发送和接收 1.代码: //接受消息 #include<stdio.h> #include<stdli ...

  4. linux 进程uhxuhao,linux 进程间通信三 消息队列以及实例

    转自 http://blog.csdn.net/liang890319/article/details/8280934 代码来自:嵌入式Linux应用开发标准教程 消息可以理解为写信给某个人,这里在应 ...

  5. linux进程管道通信缺点,Linux进程通信(IPC)的方式详解

    前言:Linux进程通信的方式 什么是进程通信?进程通信是指进程之间交换信息 进程通信方式共有6种: 管道(pipe),包括流管道(s_pipe)和有名管道(named pipe) 信号(signal ...

  6. Linux进程间通信——使用消息队列

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信--使用命名管道 一.什么是消息队列 消息队列提供了 ...

  7. Linux系统中消息队列,共享内存、信号和线程的基本操作使用方法

    Linux系统中消息队列,共享内存.信号和线程高级操作 第十一章 消息队列 10.1消息队列定义 10.2 消息队列特点 10.3 key值 10.4 创建消息队列 10.4.1 发送消息 10.4. ...

  8. c语言系统编程八:Linux进程间通信之消息队列

    Linux进程间通信之消息队列 一 消息队列概述 二 消息队列的特点 三 消息队列的创建和使用 3.1 获取系统唯一的key值 3.2 创建消息队列 3.3 查看消息队列和删除消息队列的shell命令 ...

  9. Linux的进程间通信-消息队列

    Linux的进程间通信-消息队列 微博ID:orroz 微信公众号:Linux系统技术 前言 Linux系统给我们提供了一种可以发送格式化数据流的通信手段,这就是消息队列.使用消息队列无疑在某些场景的 ...

最新文章

  1. 【VS Code】更改默认的单击打开文档模式
  2. 23种设计模式介绍(一)---- 创建型模式
  3. python字典有什么用_什么是python字典??
  4. select、poll和epoll
  5. [dfs] 洛谷 P1242 新汉诺塔
  6. ssis 表达式任务_在SSIS中执行SQL任务:SqlStatementSource表达式与可变源类型
  7. java tostring 格式化日期_ASP.NET格式化日期
  8. 上下相机贴合对位计算公式_ccd视觉自动对位贴合机主要应用在哪里?
  9. 基于jQuery动画二级下拉导航菜单
  10. 使用coin3d画个小模型
  11. php爬虫框架选用什么
  12. 软件项目开发计划编制过程
  13. Opencv+Python实现医学图片处理
  14. Python爬虫_03_urllib_xpath_JsonPath_BeautifulSoup应用及案例
  15. Linux系统开机无限重启的解决办法
  16. python根据星座测性格_星座能够测试个人的性格吗?
  17. 【联邦学习FATE框架实战】(二)用FATE从零开始实现横向逻辑回归
  18. 数据处理方法-算术编码(香农算法、java编码实现)
  19. 本地项目关联远程git仓库
  20. Picked up JDK_JAVA_OPTIONS: --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/

热门文章

  1. Linux diffstat命令
  2. Hibernate4 注解方法说明
  3. oracle赋予一个用户查询另一个用户中所有表
  4. oracle建库及plsql建表空间的用法
  5. 相同字符串的string对象不等
  6. “电脑人才”是怎么炼成的
  7. Linux 文件系统编程之系统调用和标准I/O库
  8. 中小企业网络安全提升
  9. [Web 前端] 解决因inline-block元素导致的空白间距和元素下沉
  10. jsonArray与 jsonObject区别与js取值