个人分享心得(八)——线程间通信(消息队列)

发表在 内核学习营2019-4-11 00:12 [复制链接] 1 736

本帖最后由 家定不举棋 于 2019-4-11 00:25 编辑
% F% {% j4 I5 O: D1 {* F$ F7 |: d+ C' V

消息队列

3 T% `6 N. D' P) d

消息队列 messagequeue:另一种线程间的通信方式,与邮箱不同的是能够接收的消息长度是不固定的。消息队列的结构体如下所示:

: {4 P- U0 U2 c( @* n! t
    struct rt_messagequeue
  h$ V% E* ~# D" f8 g0 ?# ~9 P    {
. x& m. D" o4 I9 H+ s        struct rt_ipc_object parent;
, R9 e! N" l6 ~  h        void                *msg_pool;5 j/ Z6 d. N  I$ f  M+ Y1 s7 z
        rt_uint16_t          msg_size;; o  f1 D( W2 w' J4 p" |/ \9 U) w
        rt_uint16_t          max_msgs;
) `7 G+ x+ z. m+ X        rt_uint16_t          entry;2 S$ _6 s$ g1 S4 ~5 j, q
        void                *msg_queue_head;
  [; S4 P% d/ s        void                *msg_queue_tail;# [- L0 F9 s- l4 L. G' A# v
        void                *msg_queue_free;  Y' M3 h2 i2 I3 D( B) Q6 O
    };
& h4 J# P, Y/ n  G% z6 W1 |2 r

msg_pool 是指向存放消息的消息池的指针,它跟数组类似,指向的是消息池的首地址;msg_size 是一条消息的长度,后面对该消息队列发送的消息长度都不能超过该长度,若发送的消息长度超过该值则会返回错误标志 -RT_ERROR;  K, x8 v1 F- o4 S1 k8 x: `8 c max_mags 是消息池中最大能容纳的消息数,当发送的消息数量超过该值时,则会返回错误标志-RT_EFULL& o. D9 x  T% a! ~* _7 L9 A; |9 T entry 是消息队列中的消息数,通过该参数可以知道消息队列中消息的具体数量;
+ d% X) k7 q  f. nmsg_queue_head 是消息链表头;msg_queue_tail 是消息链表尾;msg_queue_free  是空闲消息链表。

3 i3 C8 d6 I9 j8 }& ^$ F! w* S

消息队列的内存池大小即为每条消息的长度与消息队列中能存放的最大消息数和下一条的消息大小之和的乘积:max_msgs * (msg_size + sizeof(struct rt_mq_message))。其中下一条消息的大小为4,即 sizeof(struct rt_mq_message) 的值为4。

, l( C; F" z5 p. m+ L6 R, `' ~( z- g) f

第一步便是对创建初始化一个消息队列,这一过程的关键点便是对 msg_sizemax_msgs 两个参数进行设置,而这之中又分为静态初始化消息队列 rt_mq_init 和动态创建消息队列 rt_mq_create。对于静态初始化而言需要注意以下几点:

" @  ^. _  I) w& ^4 {5 a
    1 x) M( o1 g+ B
  1. msg_size 的值会自动4字节对齐;
  2. $ X$ {2 b. n: ~# i
  3. msg_size 的值比 pool_size 的值大时,准确的说是 (mq->msg_size + sizeof(struct rt_mq_message)) 的值比 pool_size 的值大时,max_msgs 的值就会变为0;
  4. 3 X  t% `3 w' z  [, I4 ]4 t
  5. pool_size 的值不能超过前面创建的消息队列内存大小,当该值超过了内存队列的大小的时候,初始化的时候可能不会产生错误,但是使用的时候会占用未初始化内存,从而产生未知的bug;
  6. 0 [  }" W6 M0 d
  7. flag 的值可以设置为 RT_IPC_FLAG_FIFORT_IPC_FLAG_PRIO,对于这两者的区别在前面的帖子里写过;
  8. ( b' M7 J% `% Z. \; Q! [! R  a0 k
. S, h4 f1 ^3 p  \7 z1 O

而对于动态创建消息队列而言,通过 msg_sizemax_msgs 的值动态分配内存,在动态创建的时候程序允许将 msg_size 设置为0,但是不允许将 max_msgs设置为0。(PS:在真正使用的时候都不允许将上述两个值设置为0,因为在创建的时候没有异常,但是在使用的时候会产生异常。); b8 J3 s; }3 u3 { 而对于将 msg_size 设置为0时会自动4字节对齐,那么消息队列结构体中的 msg_size 的值对齐为4,那么如果内存空间有足够的空间进行分配,那么便可以进行分配;但是当 max_msgs 的值设置为0时,向内存空间申请的消息队列内存为 RT_NULL

( _6 \+ Y4 x6 S" t/ Q' C3 R* z

在正确初始化创建消息队列后便是对其进行使用,我们可以对其以下操作:发送普通消息 rt_mq_send、发送紧急消息 rt_mq_urgent、接收消息 rt_mq_recv! p+ L$ e1 f- A7 {/ u6 \( V 不管发送紧急消息还是普通消息,size 的大小都不能超过 msg_size 的值,而对于接收消息没有这个限制的要求。因为当 size 的值大于 msg_size 时,接收的消息大小自动设置为 msg_size

3 Z6 S" ?' c$ ~" F
使用道具 举报 显示全部楼层 回复
最新评论 | 正序浏览
显示全部楼层 |楼层直达:
发表于 2019-4-11 10:34:33 | 显示全部楼层
使用道具 举报 回复
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|RT-Thread开发者社区 ( 沪ICP备13014002号-1

有害信息举报电话:021-31165890 手机:18930558079

© 2006-2019 上海睿赛德电子科技有限公司

Powered by RT-Thread

快速回复 返回顶部 返回列表