用内存映射实现posix消息队列

POSIX消息队列与System V消息队列的主要区别:
1.对POSIX队列的读总数返回最高优先级到最早消息,对SV队列到读则可以返回任意指定优先级的消息
2.当往一个空队列放置一个消息时,POSIX允许产生一个信号或启动一个线程,System V不提供此机制


消息的属性:
1.一个无符号整数的优先级(POSIX)或一个长整数的类型(SV)
2.消息的数据部分长度(可以为0)
3.数据本身(如果长度大于0)


POSIX消息队列总结:
mq_open创建一个新队列或者打开一个已经存在的队列
mq_close关闭队列
mq_unlink删除队列名,删除队列
mq_send往队列放置消息
mq_receive从一个队列中读出消息
mq_setattr和mq_getattr查询和设置队列的属性
mq_notify允许注册一个信号或者线程,在有一个消息被放置到空队列时,发送信号或者激活线程
每个消息被赋予一个小整数优先级,mq_receive总是返回最高优先级的最早消息


限制:
/proc/sys/fs/mqueue/msg_max 10
/proc/sys/fs/mqueue/msgsize_max 8192
/proc/sys/fs/mqueue/queues_max 256


创建一个新的消息队列或者打开一个已经存在的消息队列
<mqueue.h> 注意:编译加-lrt
<fcntl.h>
<sys/stat.h>
mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode,  struct mq_attr *attr);
成功返回描述字,失败返回-1并设置errno
name: 必须为/开头!!!
oflag: O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_EXCL, O_NONBLOCK


关闭消息队列,但不能删除它
mqd_t mq_close(mqd_t mqdes);
成功返回0,失败返回-1


删除消息队列,不一定马上删除消息队列,但队列名会立即删除,(真正的析构发生在引用计数为0的时候)
mqd_t mq_unlink(const char *name);
成功返回0,失败返回-1
当某个进程还没有关闭此消息队列时,调用mq_unlink时,不会马上删除队列,当最后一个进程关闭队列时,该队列被删除
int flags;
mqd_t mqd;
flags = O_RDWR | O_CREAT | O_EXCL;
mqd = mq_open("/tmp.111", flags, 0644, NULL);
if (mqd == (mqd_t)-1) {
perror("mq_open");
return 1;
}


消息队列的属性
mq_getattr mq_setattr
mqd_t mq_getattr(mqd_t mqdes, struct mq_attr *attr);
mqd_t mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr);
成功返回0,失败返回-1

收发消息

mq_send mq_receive


mq_receive返回队列中最高优先级的最早消息,而且该优先级能随该消息的内容及其长度一起返回


ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);
成功返回消息的长度,消息的实际长度,不包括消息头;失败返回-1
msg_len指示msg_ptr的长度,必须大于等于mq_msgsize
如果msg_prio不为NULL,函数返回消息的优先级
如果队列为空,调用将阻塞,如果队列设置0_NONBLOCK,调用立即返回EAGAIN



队列限制
long int open_max = sysconf(_SC_MQ_OPEN_MAX);  // -1
long int prio_max = sysconf(_SC_MQ_PRIO_MAX);  // 32768


消息通告
当往空队列放置了一个消息时,通知进程
通告方式有2种:
1. 产生一个信号
2. 创建一个线程执行一个指定的函数
mqd_t mq_notify(mqd_t mqdes, const struct sigevent *notification);
成功返回0;失败返回-1
给队列建立或者删除异步事件通知
1.如果notification非空,那么当前进程希望在有一个消息到达而且队列先前为空时得到通知,该进程被注册为接收该队列的通知
2.如果notification为空,而且当前进程目前被注册为接收该队列的通知,那么现有注册将被撤销
3.任意时刻只有一个进程可以被注册为接收队列的通知
4.当有一个消息到达一个空队列,而且已经有一个进程被注册为接收该队列的通知时,只有在没有任何线程阻塞在该队列的mq_receive调用的前提下,通知才会发送。即在mq_receive调用中的阻塞比任何通知的注册都优先
5.当该通知已经发送给它的注册进程时,其注册即被撤销。该进程必须再次调用mq_notify以重新注册

6.当调用mq_notify但是队列不为空时,通知不会发送;当队列变为空,并且有一个消息入队时,才发送通知


下面是使用内存映射实现的消息队列,消息队列的数据结构如下:


<

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用 POSIX 消息队列实现线程间通信的例子: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <mqueue.h> #define MSG_SIZE 256 #define MAX_MSG 10 mqd_t mqd; pthread_t tid[2]; pthread_attr_t attr; // 线程1:发送消息 void *send_func(void *arg) { char msg[MSG_SIZE]; int i; for (i = 0; i < MAX_MSG; i++) { memset(msg, 0, MSG_SIZE); sprintf(msg, &quot;Message %d from thread 1&quot;, i); if (mq_send(mqd, msg, strlen(msg) + 1, 0) == -1) { perror(&quot;mq_send&quot;); exit(1); } printf(&quot;Thread 1 sent: %s\n&quot;, msg); sleep(1); } } // 线程2:接收消息 void *recv_func(void *arg) { char msg[MSG_SIZE]; unsigned int prio; int i; for (i = 0; i < MAX_MSG; i++) { memset(msg, 0, MSG_SIZE); if (mq_receive(mqd, msg, MSG_SIZE, &prio) == -1) { perror(&quot;mq_receive&quot;); exit(1); } printf(&quot;Thread 2 received: %s\n&quot;, msg); sleep(1); } } int main() { struct mq_attr attr; attr.mq_flags = 0; attr.mq_maxmsg = 10; attr.mq_msgsize = MSG_SIZE; attr.mq_curmsgs = 0; if ((mqd = mq_open(&quot;/test_mq&quot;, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR, &attr)) == -1) { perror(&quot;mq_open&quot;); exit(1); } if (pthread_attr_init(&attr) != 0) { perror(&quot;pthread_attr_init&quot;); exit(1); } if (pthread_create(&tid[0], &attr, send_func, NULL) != 0) { perror(&quot;pthread_create&quot;); exit(1); } if (pthread_create(&tid[1], &attr, recv_func, NULL) != 0) { perror(&quot;pthread_create&quot;); exit(1); } if (pthread_join(tid[0], NULL) != 0) { perror(&quot;pthread_join&quot;); exit(1); } if (pthread_join(tid[1], NULL) != 0) { perror(&quot;pthread_join&quot;); exit(1); } if (mq_close(mqd) == -1) { perror(&quot;mq_close&quot;); exit(1); } if (mq_unlink(&quot;/test_mq&quot;) == -1) { perror(&quot;mq_unlink&quot;); exit(1); } return 0; } ``` 该程序创建了一个 POSIX 消息队列 `/test_mq`,其中维护了最大消息数为 10,每条消息为 256 字节。程序启动两个线程,一个用于发送消息,一个用于接收消息,它们都可以同时操作消息队列。发送线程每秒钟向队列中发送一条消息,接收线程每秒钟从队列中接收一条消息并打印出来。程序使用 `pthread_create()` 创建线程,使用 `pthread_join()` 以等待线程完成,使用 `mq_send()` 发送消息,使用 `mq_receive()` 接收消息。最后程序清理了 POSIX 消息队列

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值