1、基本概念
队列,消息队列,用于任务间通讯的数据结构。
队列可在任务与任务之间,中断和任务之间传递信息。
当队列中的信息是空的,读取消息的任务将被阻塞并等待队列数据有效。用户可指定阻塞的任务时长。当队列有消息,被阻塞的任务会被唤醒并处理新消息。
当等待的时间超过了指定的阻塞时间,即使队列中仍没有有效数据,任务也会从阻塞态转为就绪态。
当有多个消息发送至消息队列时,通常是先进入消息队列的消息先传给任务——“先进先出”。
2、工作过程
2.1 消息池初始化
在OSIniit()函数时,消息池进行初始化。
2.2 消息队列的运作机制
创建队列的时候用户可指定队列的最大消息个数,无法再次更改,每一个消息空间可以存放任意类型的数据。
当一个任务试图读一个队列时,可指定一个阻塞超时时间,在这段时间中,如果队列为空,该任务将保持阻塞状态以等待队列数据有效。当其他任务或者中断服务函数往其等待的队列写入数据后,该任务将自动由阻塞态转移为就绪态。
3、消息队列的阻塞机制
创建的队列,是每个任务都可以去对它进行读写操作的,为了保护每一个任务对它进行读操作的过程,必须要有阻塞机制。(不是很懂)
4、消息队列的应用场景
用于任务与任务间的信息交换,中断与任务见得主要通讯方式。
5、消息队列的结构
在信号量被创建时,需要自定义消息队列(也称为消息队列句柄)。
队列存取消息有两种方式:
1)FIFO模式;(先进先出模式)
2)LIFO模式;(后进先出模式)
6、常用函数讲解
1、创建消息队列函数 OSQCreate()
void OSQCreate((OS_Q*) p_q, //消息队列指针
(CPU_CHAR*) p_name, //消息队列名称
(OS_MSG_QTY) max_qty, //消息队列大小
(OS_ERR*) p_err)
在创建消息队列的时候,是需要用户定义消息队列的句柄。但是定义了消息队列的句柄并不等于创建了队列。
//例程
OS_Q queue; //声明消息队列
OS_ERR err;
OSQCreate((OS_Q*) queue,
(CPU_CHAR*) "Queue For Test",
(OS_MSG_QTY) 20,
(OS_ERR*) &err);
2、消息队列删除函数 OSQDel()
队列删除函数是根据队列句柄直接删除的。
OS_OBJ_QTY OSQDel((OS_Q*) *p_q, //消息队列指针
(OS_OPT) opt, //选项
(OS_ERR*) p_err)
//举例
OSQ queue;
OS_ERR err;
OSQDel((OS_Q*) &queue,
(OS_OPT_DEL_NO_PEND),
(OS_ERR*) &err)
3、消息队列发送函数 OSQPost()
void OSQPost((OS_Q*) p_q, //消息队列指针
(void*) p_void, //消息指针
(OS_MSG_SIZE) msg_size, //消息大小
(OS_OPT) opt, //选项
(OS_ERR*) p_err)
//举例
OSQPost((OS_Q*) &queue,
(void*) "UCOS-III", //要发送的是数据指针,将内存块首地址通过队列发送出去
(OS_MSG_SIZE) sizeof("UCOS-III"),
(OS_OPT) OS_OPT_POST_FIFO|OS_OPT_POST_ALL, //先进先出和发布全部任务的形式
(OS_ERR*) &err);
4、消息队列获取函数 OSQPend()
void *OSQPend((OS_Q*) &queue,
(OS_Tick) timeout,
(OS_OPT) opt,
(OS_MSG_SIZE*) p_msg_size,
(CPU_TS*) p_ts,
(OS_ERR*) p_err)
OS_Q queue;
OS_ERR err;
OS_MSG_SIZE msg_size;
/*获取消息队列queue的消息*/
Pmsg = OSQPend((OS_Q*) &queue,
(OS_TICK) 0, //获取时长为无限
(OS_OPT) OS_OPT_PEND_BLOCKING, //如果没有获取到信号量就等待
(OS_MSG_SIZE*) &msg_size, //获取消息的字节大小
(CPU_TS*) 0, //获取任务发送时的时间戳
(OS_ERR*) &err)