消息队列

一、函数

mq_open

头文件

mqueue.h;

原型

mqd_t mq_open(const char *name, int oflag, .../*mode_t mode,struct mq_attr* attr*/);

函数功能

创建消息队列;

参数

name :消息队列的名字,根据消息队列的规则,为了更好的可移植性,该名字必须以‘/’开头,创建一个消息队列的时候无须路径,给出名字就好,其存放位置可有自己指定(创建前后都可以)。

oflag:O_RDONLY(只读) O_WRONLY(只写) O_RDWR(可读可写)O_CREAT(创建) O_EXCL (当消息已存在时,返回EEXIST错误到errno中)O_NONBLOCK(设置非阻塞)

mode:在oflag中指定O_CREAT时,此参数是需要的。表示创建消息队列的权限,S_IRUSR,S_IWUSR,S_IXUSR,S_IRGRP,S_IWGRP,S_IXGRP,S_IROTH,S_IWOTH,S_IXOTH相或组成或者写成0777(表示rwxrwxrwx)等用八进制表示也可以。

attr:在oflag中指定O_CREAT时,此参数是需要的。存放消息队列的属性。其中mq_flags为0,表示阻塞,为O_NONBLOCK为非阻塞。

(这里可以填写哪些参数具体看:二、Posix IPC)

返回值

若创建成功则返回消息队列的描述符,否则返回-1。

mq_close函数

头文件

mqueue.h

原型

int mq_close(mqd_t mqdes);

函数功能

关闭已打开的消息队列,关闭后调用进程不可以再使用该描述符,但其消息队列并没有被删除。一个进程终止时,它的所有打开着的消息队列都关闭,就像调用了mq_close一样。

参数

mqdes 消息队列的描述符,即消息队列创建成功后的返回值。

返回值

成功返回0,失败返回-1。

mq_unlink

头文件

mqueue.h

原型

int mq_unlink(const char *name);

函数功能

从系统中删除名为name的消息队列,但删除的只是我们可以在系统中看见的文件的名字,但文件本身并没有被从磁盘上删除,除非该名称是文件的最后一个链接,并且该文件已关闭,才会将该文件真正从磁盘上删除。即如果某前该详细队列的文件还在其他进程中打开,那么不会将其从磁盘上删除,又或者这是最后一个链接,但它还为关闭,即未执行ma_close操作,或打开它的进程为结束就执行mq_unlink,它也不会从磁盘上删除。

参数

name消息队列的名称,以‘/’开始。

返回值

成功返回0,出错返回-1。

mq_getattr

头文件

mqueue.h

原型

int mq_getattr(mqd_t mqdes, struct mq_attr *attr);

函数功能

获取mqdes指的消息队列的属性,存放到attr结构体中。

struct mq_attr

{

long int mq_flags;    /* Message queue flags:0,O_NONBLOCK */

long int mq_maxmsg;   /* Maximum number of messages.  */

long int mq_msgsize;  /* Maximum message size.  */

long int mq_curmsgs;  /* Number of messages currently queued.  */

long int __pad[4];

};

参数

mqdes为消息队列描述符,attr为上面解释的存放消息队列属性的结构体。

返回值

成功返回0,失败返回-1。

mq_setattr

头文件

mqueue.h

原型

int mq_setattr(mqd_t mqdes, const struct mq_attr *attr,

struct mq_attr *oattr);

函数功能

设置消息队列的属性,但是只使用attr结构体中的mq_flags属性,以设置(O_NONBLOCK)或清除(0)非阻塞标志。该结构体的另外三个属性被忽略,每个队列的最大消息数和每个消息的最大字节数都只能在创建时设置,当前队列中的消息数是随传送消息和读取消息的操作改变的,只能读取不能设置。如果oattr非空,那么指定队列的先前属性(4个)全将返回到由该指针指向的结构体中。

参数

mqdes 消息队列的属性

attr 函数功能解释中

oattr 函数功能解释中

返回值

成功返回0,失败返回-1。

mq_send

头文件

mqueue.h

原型

int mq_send(mqd_t mqdes, const char *ptr, size_t len,

unsigned int prio);

函数功能

给描述符mqdes指向的消息队列发送消息,大小为len,内容存放在ptr中,prio为优先级。

参数

mqdes为要发送消息的消息队列描述符;

ptr为要发送的数据;

len为消息的长度;

prio为消息的优先级;

返回值

成功返回0,失败返回-1。

mq_receive

头文件

mqueue.h

原型

ssize_t mq_receive(mqd_t mqdes, char *ptr, size_t len,

unsigned int *proip);

函数功能

从描述符mqdes指向的消息队列中读取消息存放ptr中。

参数

mqdes为要从中读取消息的消息队列的描述符;

ptr为存放接受到的消息的指针;

len为接受的最大长度;

该值不能小于能加到该消息对列上的最大大小,如果len小于该值,就立即返回EMSGSIZE错误。

返回值

成功返回读取消息的内容的字节数,出错返回-1。

mq_notify

头文件

mqueue.h;

signal.h;

原型

int mq_notify(mqd_t mqdes, const struct sigevent *notification);

函数功能

为指定队列建立或删除异步事件通知。

参数

在<signal.h>中:

union signal
{
    int  sival_int;  /*整数值*/
    void *sival_ptr; /*指针值*/
};
struct sigevent
{
    int sigev_notify; /*通知类型:SIGEV_NONE、SIGEV_SIGNAL、SIGEV_THREAD*/
    int sigev_signo; /*信号值*/
    union sigval sigev_value; /*传递给信号处理函数或线程的信号值*/
    void (*sigev_notify_function)(union sigval); /*线程处理函数*/
    pthread_attr_t *sigev_notify_attributes; /*线程属性*/
};

(1).如果notification参数非空,那么当前进程希望在有一个消息到达所指定的先前为空的队列时得到通知。我们说“该进程被注册为接收该队列的通知”。

(2).如果notification参数为空指针,而且当前进程目前被注册为接收所指定队列的通知,那么已存在的注册将被撤销。

(3).任意时刻只有一个进程可以被注册为接收某个指定队列的通知。

(4).当有一个消息到达某个先前为空的队列,而且已有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用中的前提下,通知才会发出。这就是说,在mq_receive调用中的阻塞比任何通知的注册都优先。

(5).当该通知被发送给它的注册进程时,其注册即被撤销。该进程必须再次调用mq_notify重新注册(如果想要的话)。

返回值

成功返回0,失败返回-1。

二、程序举例

mqsend.c

#include<stdio.h>

#include<stdlib.h>

#include<sys/types.h>

#include<mqueue.h>

#include<sys/stat.h>

#include<string.h>

#include<unistd.h>

#include<fcntl.h>

int main(int argc, char **argv)

{

mqd_t mqd;

char *ptr;

size_t len;

unsigned int prio;

if(argc != 4)

perror("./mqsend mqueue_name size prio!\n");

len = atoi(argv[2]);

prio = atoi(argv[3]);

mqd = mq_open(argv[1], O_WRONLY);

ptr = (char *)calloc(len, sizeof(char));

strcpy(ptr, "wjj_xyd");

mq_send(mqd, ptr, len, prio);

exit(0);

}

mqreceive.c

#include<stdio.h>

#include<stdlib.h>

#include<mqueue.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

int main(int argc, char **argv)

{

int c, flags;

mqd_t mqd;

ssize_t n;

unsigned int prio;

char *buff;

struct mq_attr attr;

flags = O_RDONLY;

while((c = getopt(argc,argv, "n")) != -1)

{

switch(c){

case 'n':flags |= O_NONBLOCK;

break;

}

}

if(optind != argc - 1)

perror("mqreceive error!\n");

mqd = mq_open(argv[optind], flags);

mq_getattr(mqd, &attr);

buff = (char*)malloc(attr.mq_msgsize);

n = mq_receive(mqd, buff, attr.mq_msgsize, &prio);

printf("buff = %s, read %ld bytes, priority = %u\n",buff, (long)n, prio);

exit(0);

}

异步通知事件:

#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
mqd_t mqd;
struct mq_attr attr;
struct sigevent sigev;
char *ptr;
unsigned int prio;
size_t n;
int rc;
void sig_usr1(int signo);
 
/*读取某消息队列,消息队列名通过参数传递*/
/*当有消息放置到某个空的队列中时产生SIGUSR1信号*/
int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("Usage: mqnotifysig1 <name>\n");
        exit(1);
    }
    /*只读模式打开消息队列*/
    mqd = mq_open(argv[1], O_RDONLY);
    if(mqd < 0)
    {
        perror("打开消息队列失败");
        exit(1);
    }
    // 取得消息队列属性,根据mq_msgsize动态申请内存
    rc = mq_getattr(mqd, &attr);
    if(rc < 0)
    {
        perror("取得消息队列属性失败");
        exit(1);
    }
    /*动态申请保证能存放单条消息的内存*/
    ptr = calloc(attr.mq_msgsize, sizeof(char));
    if(NULL == ptr)
    {
        printf("动态申请内存失败\n");
        mq_close(mqd);
        exit(1);
    }
 
    //注册信号函数
    signal(SIGUSR1, sig_usr1);
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = SIGUSR1;
    //注册通知
    rc = mq_notify(mqd, &sigev); // 读取前需要再次注册
    if(rc < 0)
    {
        perror("通知注册失败");
        mq_close(mqd);
        free(ptr);
        exit(1);
    }
 
    for(;;)
    {
        pause();
    }
    return 0;
}
 
void sig_usr1(int signo)
{
    rc = mq_notify(mqd, &sigev); // 读取前需要再次注册
    if(rc < 0)
    {
        perror("通知注册失败");
        mq_close(mqd);
        free(ptr);
        exit(1);
    }
    /*接收一条消息*/
    n = mq_receive(mqd, ptr, attr.mq_msgsize, &prio);
    if(n < 0)
    {
        perror("读取失败");
        mq_close(mqd);
        free(ptr);
        exit(1);
    }
    printf("读取 %ld 字节\n优先级为 %u\n", (long)n, prio);
}

POSIX 消息队列 之 参数说明的更多相关文章

  1. Linux IPC POSIX 消息队列

    模型: #include<mqueue.h> #include <sys/stat.h> #include <fcntl.h> mq_open() //创建/获取消 ...

  2. Posix消息队列

    转载于:http://blog.csdn.net/zx714311728/article/details/53197196 1.消息队列 消息队列可以认为是一个消息链表,消息队列是随内核持续的.队列中 ...

  3. 第5章 Posix 消息队列

    5.1 概述 消息队列可以认为是一个链表.有写权限的线程可往消息队列中放置消息,有读权限的线程可以从消息队列中取走消息. 消息队列和管道/FIFO的区别: (1)消息队列往一个队列中写消息前,并不需要 ...

  4. posix 消息队列

    注意 在涉及到posix消息的函数时, gcc 编译时要加-lrt参数, 如 gcc -lrt unpipc.c mqpack.c send.c -o send gcc -lrt unpipc.c m ...

  5. Posix消息队列实现机制

    本文是对<Unix 网络编程 卷2:进程通信>的笔记. 引言 消息队列是进程间通信的一种方式,可是如果不理解他的实现原理,会有众多不理解之处,下面就结合本书中的例子,对posix消息队列来 ...

  6. POSIX 消息队列相关问题

    一.查看和删除消息队列要想看到创建的posix消息队列,需要在root用户下执行以下操作:# mkdir /dev/mqueue# mount -t mqueue none /dev/mqueue删除 ...

  7. Linux IPC实践(7) --Posix消息队列

    1. 创建/获取一个消息队列 #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For m ...

  8. 进程间通信--POSIX消息队列

    相关函数: mqd_t mq_open(const char *name, int oflag); mqd_t mq_send(mqd_t mqdes, const char *msg_ptr, si ...

  9. POSIX 消息队列 之 概述 链接方式

    NAMEmq_overview —— POSIX消息队列概述 DESCRIPTIONPOSIX消息队列允许进程以消息的形式交换数据.此API与System V消息队列(msgget(2),msgsnd ...

随机推荐

  1. Hash索引和BTree索引

    索引是帮助mysql获取数据的数据结构.最常见的索引是Btree索引和Hash索引. 不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引:而Mermory默认的索引是 ...

  2. UVALive 5984

    题目链接:Save the Students! #include<stdio.h> #include<string.h> #include<iostream> #i ...

  3. (C#基础)反射理解

    这个知识点很基础. 代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; n ...

  4. java基本类型的大小

    1个字节是8位byte 1字节short 2字节int 4字节long 8字节float 4字节double 8字节char 2字节boolean 1字节======================= ...

  5. TClientDataSet 的Filename 和 open方法

    cdsAdd.Open 不能用open,因为这个是DataSet的通用方法,不会检测文件名的,文件名是CDS特有的

  6. 《Python》反射、内置方法(__str__,__repr__)

    一.反射 通过字符串的形式操作对象相关的属性.(使用字符串数据类型的变量名来获取这个变量的值) Python中的一切事物都是对象(都可以使用反射) 反射类中的变量 反射对象中的变量 反射模板中的变量 ...

  7. LINK : fatal error LNK1123

    转: LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 这个是由于日志文件引起的,可以将 项目\属性\配置属性\清单工具\输入和输出\嵌入清单:原来 ...

  8. 玩转X-CTR100 l STM32F4 l 电机正交编码器

    我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器的电机正交编码器,X- ...

  9. Obtain older GMT versions

    ftp://ftp.soest.hawaii.edu/gmt/legacy/

  10. Android Mms专题之:Mms源码结构

    从软件的功能角度来讲,Mms分为对话列表,消息列表,短信编辑,彩信编辑,短信显示,彩信显示和配置. 从实现的角度来看,它分为GUI展示层,发送/接收,彩信解析,彩信附件,信息数据等,这些分类对应着源码 ...