消息队列

一、函数

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. SPOJ UMR 10A 计算几何

    DES:顺时针给出构成凸多边形的点.然后有Q个询问任意给出两个点的编号,询问由这两个点的连线将多边形分成的两部分面积较小的部分面积大小. 比赛时直接每次连线后求多边形求面积超时了.正确解法是求出利用叉 ...

  2. html 列表相关信息

    无序列表 无序列表是一个项目的列表,此列项目使用粗体圆点(典型的小黑圆圆标记) 无序列表始于<ul>标签.每个列表项始于<li> <ul>   <li> ...

  3. jenkins的流水线pipeline+项目实验php

    声明:实验环境使用Jenkins的应用与搭建的环境 新建一个流水线 pipeline脚本语法架构 node('slave节点名'){ def 变量 #def可以进行变量声明 stage('阶段名A') ...

  4. Oracle sqlloader

    一.SQL*LOADER简介 SQL*Loader是oracle提供的可以从多种平面文件中向数据库中加载数据的工具,使用sqlldr工具可以在很短的时间内向数据库中加载大量的数据,像把制作好的exce ...

  5. Oracle top 查询TOP SQL

    有时Oracle数据库服务器,系统CPU爆高,通过Top命令可以查看到占用CPU最高的进程 我们需要记住前几个TOP的pid号,带入下面的SQL,到数据库中查询运行的进程.服务器.用户.SQL.等待等 ...

  6. Final阶段第1周/共1周 Scrum立会报告+燃尽图 02

    作业要求[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2481] 版本控制:https://git.coding.net/liuyy08 ...

  7. koa 核心源码介绍

    链接来源 Request,Context,Response  在代码运行之前就已经存在的 Request和Response自身的方法会委托到Context中. Context源码片段 var dele ...

  8. Java实现交换两个String

    在Java中我们所使用的实例变量其实都是一个引用,所以如果要求实现一个swap(String A, String B)这种函数时无法实现的,因为在类方法的定义中是先对行参进行地址传递,然后对形参修改, ...

  9. jQuery 3.1 参考手册.CHM离线版下载

    制作了一份jQuery 3.1 参考手册.CHM离线版供大家使用 点击下载 预览一下

  10. 【Android 】查看被测应用程序package和launchable-activity

    [appt] appt 工具所在位置..\sdk\build-tools\23.0.1\aapt.exe #查看Package>aapt dump badging C:\QQemail.apk ...