消息队列、信号量以及共享内存被称作 XSI IPC,它们均来自system V的IPC功能,因此具有许多共性。

键和标识符:

  内核中的每一种IPC结构(比如信号量、消息队列、共享内存)都用一个非负整数的标识符加以标示(如共享内存的shmid、信号量的semid、以及消息队列的msgid)。不同于文件描述符,IPC标识符不是一个小的非负整数,它是一个int型的整数,当一个标识符被创建,以后又被删除时,这个整数持续加1,达到整型的最大值后,重新回到0。

  但是每一个IPC对象在内核中的标识符只能在内部被识别,为了让不同的进程能够在同一个IPC对象上汇合,还需要一个外部的标识来表示一个IPC 对象,这就是key 键值。或者可以这样理解:标识符是一个打开了的IPC对象的描述符,而键值则让进程获得这个标识符。

  当我们通过一个键值创建了一个IPC对象以后,就可以用这个IPC对象的标识符操作这个IPC对象。例如当进程用指定的键值获得一个共享内存的标识符shmid以后,就可以通过这个标识符将共享内存映射到自身的地址空间上,当然后续对共享内存的操作也是基于这个标识符。

消息队列编程:

  消息队列作为XSI IPC的一种,许多实现和操作和前面描述的信号量和共享内存有很多相似的地方。先简述一下消息队列的原理:消息队列的本质就是一个消息的链表,而每个消息的结构如下

struct msgbuf {

                    long mtype;       /* message type, must be > 0 */

              char mtext[1];    /* message data */

           };

mtype:消息的类型        mtext[]: 消息中的数据

也就是说消息队列就是一个数据域是以上结构体的链表。既然了解了一个消息队列的本质就是一个链表,可以想象,如果进程间要通过消息队列通信,那么发送消息的进程的主要工作就是要构建一个数据域,然后交给内核来插入到链表中,而接收消息的进程就是通过内核函数来将数据从消息队列中取出来。消息队列还有如下特点:

 *消息队列的消息类型可以不同,进程取出消息时可以指定消息类型取出需要的消息

 *当进程取出一条消息后,该消息会立即被移出消息队列

利用消息队列通信主要由以下操作完成:

 *创建/打开消息队列   :int msgget(key_t key, int msgflg);

 *发送消息                 :int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)

 *接收消息                 :ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg)

 *删除消息队列           :int msgctl(int msqid, int cmd, struct msqid_ds *buf)

这些函数都可以通过man命令查到具体的用法,这里就不在详细解释,下面是一个测试的范例:

send 程序:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h> #define TEXT_SZ 2048
struct msgt
{
long msgtype;
char msgtext[TEXT_SZ];
}; int main()
{
int msgid;
key_t key;
int running = ;
struct msgt msg_data;
int msgtype;
key = ftok("/home/application/massage_queue",);
//创建消息队列
msgid = msgget(key, IPC_CREAT);
//循环
while(running)
{
printf("Please Input msgtype,Input 0 to quit!\n");
scanf("%d",&msgtype);
printf("Please Input datas!\n"); //从终端读取数据
scanf("%s",msg_data.msgtext);
//将数据写入消息队列
msg_data.msgtype = msgtype;
msgsnd(msgid, &msg_data, sizeof(msg_data), ); if(strncmp(msg_data.msgtext,"end",)==)
{
msgsnd(msgid, "end", , );
running = ;
}
}
//删除消息队列
msgctl(msgid, IPC_RMID, );
return ; }

receive 程序:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <unistd.h> #define TEXT_SZ 2048
struct msgt
{
long msgtype;
char msgtext[TEXT_SZ];
}; int msgid;
void childprocess()
{
struct msgt msg_d;
int running = ;
while(running)
{
//接受消息队列中的数据
msgrcv(msgid, &msg_d, sizeof(msg_d), ,);
//打印数据
printf("Receive datas from queue:%s",msg_d.msgtext);
if(strncmp(msg_d.msgtext,"end",)==)
{
running = ;
}
} }
int main()
{ key_t key;
pid_t pid;
int i;
key = ftok("/home/application/massage_queue",);
//打开消息队列
msgid = msgget(key, IPC_EXCL); for(i=;i<;i++)
{
pid = fork();
if(pid<)
{
printf("fork error!\n");
}
else if(pid==)
{
childprocess();
}
} return ;
}

当两个程序运行起来以后可以发现通过send成序发送的数据在receive 中可以接收到,说明这些函数的调用很成功,同时也证明了消息队列的通信是成功的。

Linux 消息队列编程的更多相关文章

  1. linux消息队列编程实例

    转自:linux 消息队列实例 前言: 消息队列就是一个消息的链表.可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向其中按照一定的规则添加新消息:对消息队列有读权 ...

  2. linux消息队列应用编程

    消息队列:  消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法   每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值   消息队列也有管道一样的不足,就是每个消息的 ...

  3. LINUX消息队列实战之一

    前言 能说能抄能论皆不算,能写能打才是真功夫. 唠叨 反正我也是一个孤独的程序猿,多说一些奇奇怪怪的唠叨也无妨,第一次写消息队列,书本的东西和实战很不同,根据实战总结的一些注意事项会和大家分享,也敲打 ...

  4. linux 消息队列的限制

    消息队列的系统限制 作者:冯老师,华清远见嵌入式学院讲师. 消息队列是System V的IPC对象的一种,用于进程间通信,会受到系统的限制,本文主要描述了三个限制.第一:议个消息的最大长度:第二:消息 ...

  5. linux消息队列通信

    IPC机制 进程间通信机制(Inter Process Communication,IPC),这些IPC机制的存在使UNIX在进程通信领域手段相当丰富,也使得程序员在开发一个由多个进程协作的任务组成的 ...

  6. Linux消息队列应用

    #include"sys/types.h" #include "sys/msg.h" #include "unistd.h" #includ ...

  7. linux消息队列操作

    对消息队列的操作无非有以下三种类型: 1. 打开或创建消息队列消息队列的内核持续性要求每一个消息队列都在系统范围内相应唯一的键值,所以,要获得一个消息队列的描写叙述字,仅仅需提供该消息队列的键值就可以 ...

  8. linux消息队列的使用

    消息队列 *消息队列是内核地址空间中的内部链表,通过内核在各个进程之间传递的内容.消息顺序发送到消息队列中,每个消息队列都有IPC标识符唯一地进行标识. msgbuf结构 struct msgbuf{ ...

  9. Linux消息队列

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

随机推荐

  1. Device Tree常用方法解析

    Device Tree常用方法解析 Device Tree在Linux内核驱动中的使用源于2011年3月17日Linus Torvalds在ARM Linux邮件列表中的一封邮件,他宣称“this w ...

  2. 天涯html&css基础框架

    html申明 对ie6-8在html中添加no-css3这个class和各个版本的class,对ie7以下添加lte7这个class,然后根据我们目前使用浏览器的比例,把第一的ie6放在判断第一位. ...

  3. STM32 定时器用于外部脉冲计数

    STM32 定时器用于外部脉冲计数 第一步,设置GPIO GPIO_InitTypeDef GPIO_InitStructure; /* PA0,PA12-> 左右脉冲输入 */GPIO_Ini ...

  4. Bitbucket Pull Request和fork

    本文参考了http://blog.jobbole.com/76854/   Pull Request在Forking工作流中使用,这个也同样适用于小团队的开发协作和第三方开发者向开源项目的贡献.当你要 ...

  5. JAVA基础英语单词表(下)

    quantity                     / 'kwɔntiti /                    量,数量 query                             ...

  6. Java验证码和ajax判断

    关于来了解相关的api BufferedImage(int width, int height, int imageType) 构造一个类型为预定义图像类型之一的 BufferedImage. Buf ...

  7. ibatis 开发中的经验 (一)ibatis 和hibernate 在开发中的理解

    这个项目的底层是用ibatis框架完毕,这几天也是都在用这个框架写代码,也有了一些简单的理解,把项目拿过来后基本的配置都已经配置好了,比方一些事务.日志控制等,在开发中主要用到的是写SQL语句以及熟悉 ...

  8. POJ 1185 炮兵

    是中国标题.大家都说水问题.但是,良好的1A它? 标题效果: 给出n*m的矩阵,当某个单元格有炮兵部队时它的上下左右两格(不包含斜着的方向)是这支部队的攻击范围.问在两支部队之间不可能相互攻击到的情况 ...

  9. Linux命令之ssh

    一. 配置ssh 1. 命令 ssh-keygen [选项] 2. 说明 用于为“ssh”生成.管理和转换认证密钥,它支持RSA和DSA两种认证密钥 3. 选项 -C:添加注释 -f:指定用来保存密钥 ...

  10. An NIO.2 primer--reference

    Part 1: The asynchronous channel APIs The More New I/O APIs for the Java™ Platform (NIO.2) is one of ...