消息队列:

        消息队列提供了一个从一个进程向另外一个进程发送一块数据的方法
        每个数据块都被认为是有一个类型,接收者进程接收的数据块可以有不同的类型值
        消息队列也有管道一样的不足,就是每个消息的最大长度是有上限的(MSGMAX),每个消息队列的总的字节数是有上限的(MSGMNB),系统上消息队列的总数也有一个上限(MSGMNI)
  对比管道和消息:
  管道:流管道        消息:有边界
  先进先出              可以后进入、先出来
  消息大小三大限制
  cat /proc/sys/kernel/msgmax最大消息长度限制
  cat /proc/sys/kernel/msgmnb消息队列总的字节数
  cat /proc/sys/kernel/msgmni消息条目数

  IPC对象数据结构
      内核为每个IPC对象维护一个数据结构
        struct ipc_perm {
            key_t __key;       /* Key supplied to xxxget(2) */
            uid_t uid;         /* Effective UID of owner */
            gid_t gid;         /* Effective GID of owner */
            uid_t cuid;        /* Effective UID of creator */
            gid_t cgid;        /* Effective GID of creator */
            unsigned short mode;   /* Permissions */
            unsigned short __seq;  /* Sequence number */
        };

struct msqid_ds {
            struct ipc_perm msg_perm;     /* Ownership and permissions */
            time_t            msg_stime;    /* Time of last msgsnd(2) */
            time_t            msg_rtime;    /* Time of last msgrcv(2) */
            time_t            msg_ctime;    /* Time of last change */
            unsigned long   __msg_cbytes; /* Current number of bytes in queue (nonstandard) */
            msgqnum_t        msg_qnum;     /* Current number of messages in queue */
            msglen_t        msg_qbytes;   /* Maximum number of bytes allowed in queue */
            pid_t            msg_lspid;    /* PID of last msgsnd(2) */
            pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
        };

消息队列在内核中的表:

  

消息队列函数:
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    intmsgget(key_t key, intmsgflg);
    intmsgctl(intmsqid, intcmd, structmsqid_ds *buf);
    intmsgsnd(intmsqid, const void *msgp, size_tmsgsz, intmsgflg);
    ssize_tmsgrcv(intmsqid, void *msgp, size_tmsgsz, long msgtyp, intmsgflg);

  msgget函数
        功能:用来创建和访问一个消息队列
        原型:intmsgget(key_t key, intmsgflg);
        参数:
              key: 某个消息队列的名字
              msgflg:由九个权限标志构成,它们的用法和创建文件时使用的mode模式标志是一样的
            返回值:成功返回一个非负整数,即该消息队列的标识码;失败返回-1

     msgget函数参数关系图:

     

   msgctl函数
        功能:消息队列的控制函数
        原型:intmsgctl(intmsqid, intcmd, structmsqid_ds *buf);
        参数:
            msqid: 由msgget函数返回的消息队列标识码
            cmd:是将要采取的动作,(有三个可取值)
        返回值:成功返回0,失败返回-1
        cmd:将要采取的动作(有三个可取值),分别如下:

     

消息队列的发送和接受:

  msgsnd函数
        功能:把一条消息添加到消息队列中
        原型:intmsgsnd(intmsqid, const void *msgp, size_tmsgsz, intmsgflg);
        参数:
            msgid: 由msgget函数返回的消息队列标识码
            msgp:是一个指针,指针指向准备发送的消息,
            msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
            msgflg:控制着当前消息队列满或到达系统上限时将要发生的事情
        返回值:成功返回0;失败返回-1
        msgflg=IPC_NOWAIT表示队列满不等待,返回EAGAIN错误。
        消息结构在两方面受到制约。首先,它必须小于系统规定的上限值;其次,它必须以一个long int长整数开始,接收者函数将利用这个长整数确定消息的类型
        消息结构参考形式如下:
                    structmsgbuf {
                        long  mtype;
                        char mtext[100];
                    }

msgrcv函数
        功能:是从一个消息队列接收消息
        原型:ssize_tmsgrcv(intmsqid, void *msgp, size_tmsgsz, long msgtyp, intmsgflg);
        参数:
            msgid: 由msgget函数返回的消息队列标识码
            msgp:是一个指针,指针指向准备接收的消息,
            msgsz:是msgp指向的消息长度,这个长度不含保存消息类型的那个long int长整型
            msgtype:它可以实现接收优先级的简单形式
            msgflg:控制着队列中没有相应类型的消息可供接收时将要发生的事
        返回值:成功返回实际放到接收缓冲区里去的字符个数,失败返回-1
        msgtype=0返回队列第一条信息
        msgtype>0返回队列第一条类型等于msgtype的消息 
        msgtype<0返回队列第一条类型小于等于msgtype绝对值的消息,并且是满足条件的消息类型最小的消息
        
        msgflg=IPC_NOWAIT,队列没有可读消息不等待,返回ENOMSG错误。
        msgflg=MSG_NOERROR,消息大小超过msgsz时被截断
        msgtype>0且msgflg=MSG_EXCEPT,接收类型不等于msgtype的第一条消息。

消息队列综合api使用:

  同一个进程,使用消息队列代码示例:

  

 #include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include<errno.h>
#include<string.h>
#include <sys/types.h>
#include <unistd.h>
struct msg_buf
{
long mtype;
char data[];
}; /* 注意long 和int在32bit 和 64bit系统之下是不一样的
structmsg_buf
{
long mtype;
char data[255];
};
*/ int main()
{
key_t key;
int msgid;
int ret;
struct msg_buf msgbuf;
int msgtype = getpid();
//系统建立IPC通讯 (消息队列、信号量和共享内存) 时必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
key=ftok("./msgfile",'a');
printf("key =[%x]\n",key); printf("sizeof(long):%ld, sizeof(int):%d \n", sizeof(long), sizeof(int));
//用来创建和访问一个消息队列
msgid=msgget(key, IPC_CREAT |IPC_EXCL|); //通过文件对应 if(msgid==-)
{
if (errno == EEXIST)
{
printf("EEXIST:.....\n");
key=ftok("./msgfile",'a');
msgid=msgget(key, IPC_CREAT|); //通过文件对应
}
else
{
printf("create error\n");
perror("msget: \n");
return -;
} }
printf("msgid:%d \n", msgid); msgbuf.mtype = msgtype; // getpid(); printf("getpid(): %d \n", getpid());
strcpy(msgbuf.data,"hello world!");
//把一条data消息添加到消息队列,IPC_NOWAIT表示队列满不等待,返回EAGAIN错误
ret = msgsnd(msgid,&msgbuf, sizeof(msgbuf.data), IPC_NOWAIT);
if(ret==-)
{
printf("send message err\n");
perror("senderr");
return -;
}
sleep(); memset(&msgbuf,,sizeof(msgbuf));
//是从一个消息队列接收消息,队列没有可读消息不等待,返回ENOMSG错误
ret=msgrcv(msgid, &msgbuf, sizeof(msgbuf.data), msgtype, IPC_NOWAIT);
if(ret==-)
{
printf("recv message err\n");
perror("dd");
return -;
}
printf("recvmsg =[%s]\n",msgbuf.data);
return ;
}

编译执行程序,结果如下所示:

消息队列项目开发案例(消息队列实现回射客户/服务器)示意:

linux消息队列应用编程的更多相关文章

  1. linux消息队列编程实例

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

  2. Linux 消息队列编程

    消息队列.信号量以及共享内存被称作 XSI IPC,它们均来自system V的IPC功能,因此具有许多共性. 键和标识符: 内核中的每一种IPC结构(比如信号量.消息队列.共享内存)都用一个非负整数 ...

  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. angular 4 路由变化的时候实时监测刷新组件

    当路由变化的时候刷新组件 比如说要刷新header组件 在header.ts里 import {Router, NavigationEnd} from "@angular/router&qu ...

  2. 170417、Dubbo与Zookeeper、SpringMVC整合和使用(负载均衡、容错)

    前言:互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo是一个分布式服务框架,在这种情况下诞生的.现在核心业务抽取出来,作为独立的服 ...

  3. 170320、使用快照和AOF将Redis数据持久化到硬盘中

    前言 我们知道Redis是一款内存服务器,就算我们对自己的服务器足够的信任,不会出现任何软件或者硬件的故障,但也会有可能出现突然断电等情况,造成Redis服务器中的数据失效.因此,我们需要向传统的关系 ...

  4. CSS Sprites 原理技术介绍及其优化方法

    先期的准备工作 应对一个项目后期维护成本大的问题,我们最好的解决方案就是在开始前制定一系列的规范来限制问题的产品.好的开始是成功的一半.对于CSS Sprites,在项目开始前,我们要充分认识一个产品 ...

  5. JAVAWEB的Listener

    学习监听器 1监听器是什么 :监听对象的变化或者监听事件的触发 2有什么作用:当被监听的对象状态改变时,触发对应的方法 3怎么用: ①声明监听器,(继承对应的监听器) ②重写监听方法,并实现自己需要的 ...

  6. Quartz.net 基于配置的调度程序实践

    1.Nuget 搜索并安装Quartz.net 2.3.3  2.添加配置到App.config <?xml version="1.0" encoding="utf ...

  7. Macbook pro 13" Installs Ubuntu 18.04

    最新版的 MacBook对Ubuntu的支持(或者反过来?)不是很好,但是除了Suspend和resume功能没找到方法使用外,其他都还好,可用. 1.mac在OSX中先安装refind引导,如果开启 ...

  8. Git 使用配置

    应用情景:使用Git前需要配置 user.name 和 user.email 信息.Git利用这些信息记录谁进行了什么样的操作.Git属于分布式版本管理系统,开发者很多,配置这个就相当于自报家门,告诉 ...

  9. 浅谈pipreqs组件(自动生成需要导入的模块信息)

    简介 pipreqs的作用 一起开发项目的时候总是要搭建环境和部署环境的,这个时候必须得有个python第三方包的list,一般都叫做requirements.txt. 如果一个项目使用时virtua ...

  10. LNMP环境修改上传文件大小

    LNMP环境修改上传文件大小限制     如果网页上传文件大小大于nginx或php设定的值,就会造成无法上传,显示IO error错误. 如何解决这个问题呢?我们需要更改两个配置: 1.  ngin ...