消息队列

一、函数

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. Phython笔记初识

    Phython笔记初识   Python 1898 第一版本 1991 荷兰人 Guido  协议 Gpl                     动态语音类型  

  2. STM32F103各PIN脚封装图

    1.36PIN 2.48PIN 3.64PIN 4.100PIN STM32ZET6详细pin脚图

  3. 多种方法实现 python 线程池

    最近在做一个爬虫相关的项目,单线程的整站爬虫,耗时真的不是一般的巨大,运行一次也是心累,,,所以,要想实现整站爬虫,多线程是不可避免的,那么python多线程又应该怎样实现呢?这里主要要几个问题(关于 ...

  4. MySQL 中Index Condition Pushdown (ICP 索引条件下推)和Multi-Range Read(MRR 索引多范围查找)查询优化

    一.ICP优化原理 Index Condition Pushdown (ICP),也称为索引条件下推,体现在执行计划的上是会出现Using index condition(Extra列,当然Extra ...

  5. ORACLE telnet 1521 不通及ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务的解决

    服务器上安装了oracle11g , 防火墙上已经增加1521 入站规则.但是内网客户端配置好了TNS无法连接.telnet 1521 不通. 需要在服务器上\product\10.2.0\db_1\ ...

  6. servlet基础(组成与生命周期)

    servlet基础作用:servlet是运行在Web服务器或应用服务器上的程序:担当web浏览器或其他HTTP客户程序发出的请求与HTTP服务器上的数据库或应用程序之间的中间层.1.读取客户程序发送的 ...

  7. Individual work 总结

    不得不说,这是我上大学以来所花时间最长.收获最多的个人项目之一.在此之前,虽然也上过面向对象等课程,课程对编程代码量的要求并不比这个小,但是由于从没有如这次这般,完全靠自己学习新的编程语言并进行编程实 ...

  8. 在eclipse中创建web项目(非myeclipse)

    如何创建dynamic web project项目 本文的演示是从本地文件创建dynamic web project,从svn检出的同时创建dynamic web project于此类似.我们推荐使用 ...

  9. SWIFT推送之本地推送(UILocalNotification)

    本地推送通知是通过实例化UILocalNotification实现的.要实现本地化推送可以在AppDelegate.swift中添加代码实现,本事例是一个当App进入后台时推送一条消息给用户. 1.首 ...

  10. Netty网络聊天室之会话管理

    写过web的同学们应该对Session这个东西很熟悉.浏览器第一次与服务器建立连接的时候,服务器就会自动为之分配一个Session.Session可以用来判断用户是否经过登录验证,也可以保存用户的各种 ...