一 关于消息队列

  消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法,而且,每个数据块都被认为含有一个类型,接收进程可以独立地接受含有不同类型值的数据块。可以通过发送消息来几乎完全避免命名管道的同步和阻塞问题。但是,与管道一样,每个数据块都有一个最大长度的限制,系统中所有队列所包含的全部数据块的总长度都有一个上限。

  与命名管道相比,消息队列的优势是,它独立于发送和接受进程而存在,这消除了在同步命名管道的打开和关闭时可能产生的一些困难。

二 相关函数

#include <sys/msg.h>
//msgget函数创建和访问一个消息队列
int msgget(key_t key,
      int msgflg   //由IPC_CREAT定义的一个特殊位必须和权限标志按位或才能创建一个新的消息队列,在设置IPC_CREAT标志时,如果给出的是一个已有消息队列的键也不会产生错误。如果消息队列已有,则IPC_CREAT标志就被悄悄地忽略掉。
      );        //成功时msgget函数返回一个正整数,即队列标识符,失败时返回-1 //msgsnd函数用来把消息添加到消息队列中
int msgsnd(int msqid,        //是由msgget函数返回的消息队列标识符
       const void *msg_ptr,  //是一个指向准备发送消息的指针
       size_t msg_sz,      //是msg_ptr指向的消息的长度,它不包括长整型消息类型成员变量的长度
       int msgflg        //是控制在当前消息队列满或队列消息到达系统范围的限制时将要发生的事情。
                     //如果msgflg中设置了IPC_NOWAIT标志,函数将立刻返回,不发送消息并且返回值为-1.如果msgflg中IPC_NOWAIT标志被清除,则发送进程将挂起以等待队列中腾出可用空间。
      );

//msgrcv函数从一个消息队列中获取消息
int msgrcv(int msqid,        //由msgget函数返回的消息队列标识符
       void *msg_ptr,      //是一个指向准备接受消息的指针,消息必须以一个长整数型成员变量开始
       size_t msg_sz,      //是msg_ptr指向的消息的长度,它不包括长整型消息类型成员变量的长度
       long int msgtype,    //如果值为0,就获取队列中的第一个可用消息;如果它的值大于零,将获取具有相同消息类型的第一个消息;如果它的值小于零,将获取消息类型等于或小于msgtype的绝对值的第一个消息
       int msgflg        //用于控制当队列中没有相应类型的消息可以接受时将发生的事情
      );              //成功时msgrcv函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息,失败时返回-1 //msgctl函数与共享内存的控制函数相似
int msgctl(int msqid,          //是msgget返回的消息队列标识符
       int cmd,           //将要采取的动作
       struct msqid_ds *buf
      );               //成功时返回0,失败时返回-1,如果删除消息队列时,某个进程正在msgsnd或msgrcv函数中等待,这两个函数将失败

msgctl中第二个参数要采取的动作:
  IPC_STAT:把msqid_ds结构中的数据设置为消息队列的当前关联值
  IPC_SET:如果进程有足够的权限,就把消息队列的当前关联值设置为msqid_ds结构中给出的值
  IPC_RMID:删除消息队列

三 实验

msg1.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h> #include <sys/msg.h> struct my_msg_st{
    long int my_msg_type;
    char some_text[BUFSIZ];
}; int main(){
    int running=1;
    int msgid;
    struct my_msg_st some_data;
    long int msg_to_receive=0;
    
    //首先建立消息队列
    msgid=msgget((key_t)1234,0666 | IPC_CREAT);
    if(msgid==-1){
        fprintf(stderr,"msgget failed with error:%d\n",errno);
        exit(EXIT_FAILURE);
    }
    
    //从队列中获取消息,直到遇见end消息为止,最后删除队列
    while(running){
        if(msgrcv(msgid,(void *)&some_data,BUFSIZ,msg_to_receive,0)==-1){
            fprintf(stderr,"msgrcv failed with error:%d\n",errno);
            exit(EXIT_FAILURE);
        }
        printf("You wrote:%s",some_data.some_text);
        if(strncmp(some_data.some_text,"end",3)==0){
            running=0;
        }
    }
    if(msgctl(msgid,IPC_RMID,0)==-1){
        fprintf(stderr,"msgctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

msg2.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h> #include <sys/msg.h>
#define MAX_TEXT 512 struct my_msg_st{
long int my_msg_type;
char some_text[MAX_TEXT];
}; int main(){
int running=;
struct my_msg_st some_data;
int msgid;
char buffer[BUFSIZ]; msgid=msgget((key_t),|IPC_CREAT);
if(msgid==-){
fprintf(stderr,"msgget failed with error:%d",errno);
exit(EXIT_FAILURE);
}
while(running){
printf("Enter some text:");
fgets(buffer,BUFSIZ,stdin);
some_data.my_msg_type=;
strcpy(some_data.some_text,buffer); if(msgsnd(msgid,(void *)&some_data,MAX_TEXT,)==-){
fprintf(stderr,"msgsnd failed\n");
exit(EXIT_FAILURE);
}
if(strncmp(buffer,"end",)==){
running=;
}
}
exit(EXIT_FAILURE);
}

Linux学习笔记28——消息队列的更多相关文章

  1. Linux进程间通信IPC学习笔记之消息队列(SVR4)

    Linux进程间通信IPC学习笔记之消息队列(SVR4)

  2. Linux进程间通信IPC学习笔记之消息队列(Posix)

    基础知识: 消息队列可认为是一个消息链表,有足够写权限的线程可往队列中放置消息,有足够读权限的线程可以从队列中取走消息.在某个进程往一人队列写入消息之前,并不需要另外某个进程在该队列上等待消息的到达. ...

  3. Redis学习笔记~实现消息队列比MSMQ更方便

    什么是队列:简单的说就是数据存储到一个空间里(可以是内存,也可以是物理文件),先存储的数据对象,先被取出来,这与堆栈正好相反,消息队列也是这样,将可能出现高并发的数据进行队列存储,并按着入队的顺序依次 ...

  4. PetShop 4.0学习笔记:消息队列MSMQ

    直到今天才知道,在我们每天都在用的Window系统里还有这么好用的一个编程组件:消息队列.它能够解决在大数据量交换的情况下的性能问题,特别是BS系统的数据库性能.而且它的异步处理方式能给程序员最大的便 ...

  5. Spring学习笔记3——消息队列(rabbitmq), 发送邮件

    本节的内容是用户注册时,将邮箱地址先存入rabbitmq队列,之后返回给用户注册成功:之后消息队列的接收者从队列中获取消息,发送邮件给用户. 一.RabbitMQ介绍     如果之前对rabbitm ...

  6. Linux 学习笔记

    Linux学习笔记 请切换web视图查看,表格比较大,方法:视图>>web板式视图 博客园不能粘贴图片吗 http://wenku.baidu.com/view/bda1c3067fd53 ...

  7. Linux学习笔记(一)2015.4.13

    研究生由单片机转Linux学习 首先安装VMware虚拟机,用的是VMware 10.0 在VMware 10.0上安装视频上推荐的Red Hat Linux 5 安装后正式进入Linux学习 笔记1 ...

  8. Linux 学习笔记之超详细基础linux命令 Part 1

    Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122   说明:主要是在REHL Server 6操作系统下进行的测试 --字符界面虚拟终端与图形界面之间的切 方法:[ ...

  9. Intel® Media SDK Media Samples Linux 学习笔记(转)

    最近折腾intel media sdk,主要硬件平台是在HD4600的核显上进行测试,intel media sdk是intel提供的一种基于核显的硬件编解码的解决方案,之前已经有使用ffmpeg进行 ...

随机推荐

  1. WPF Radio组的绑定

    都是控件编,RadioButtion 简单绑定使用,model.cs下边定义属性 private int _isSuccess; public int IsSuccess { get { return ...

  2. 菜鸟日记之JSP1

                             JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它 是由Sun Microsyste ...

  3. 『重构--改善既有代码的设计』读书笔记----Change Reference to Value

    如果你有一个引用对象,很小且不可改变,而且不易管理,你就需要考虑将他改为一个值对象.在Change Value to Reference我们说过,要在引用对象和值对象之间做选择,有时候并不容易,有了重 ...

  4. 关于A*寻路算法的认识

    最近要参加学校的APP比赛,我们组做的是一个3D迷宫的小APP,我负责的是迷宫的生成与寻路. 寻路算法选择的是A*寻路算法,具体参考的是下面的这篇博客. 本文主要是谈谈自己对A*算法的理解,具体细节, ...

  5. 如何禁用easyui-linkbutton 中的Click事件

    eg: <a id="btn" href="#" class="easyui-linkbutton" data-options=&qu ...

  6. js中的forin

    前言 自己在平时没事干练练手,发现的以前一直以为是错的.幸亏今天知道了,要不说起来自己还不知道呢. 过程 遍历前置页面上的textbox,给他们赋值(js). 一开始自己用forin遍历的. 如论如何 ...

  7. js设计模式--鸭子类型

    1.简介 JavaScript没有提供传统面向对象语言的类式继承通过原型委托的形式实现对象与对象之间的继承没有对抽象类和接口的支持 编程语言按数据类型可分为静态类型语言和动态类型语言 变量的类型要到程 ...

  8. thinkphp我掉下的一些坑

    1.数据库连接,需要连接没有数据表前缀 如下,第二个参数必须为null,我之前写的是'',结果给我默认加了前缀 $User = M('User',Null,'DB_CONFIG2'); 2.AJAX获 ...

  9. Sublime Text 2中前端必备的常用插件

    Sublime Text 2安装的插件和所有预置的插件全部在Packages文件下,可以直接通过”preferences“—>”Browse Pakcages“来访问. Sublime Text ...

  10. SurfaceFlinger服务概述和学习计划

    SurfaceFlinger服务负责绘制Android应用程序的UI 实现相当复杂,要从正面分析它的实现不是一件容易的事.既然不能从正面分析,我们就想办法从侧面分析.说到底,无论SurfaceFlin ...