首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

uC/OSIII的消息队列处理机制(3)

uC/OSIII的消息队列处理机制(3)

延迟推送中,OS_IntQPost()函数的接收者是中断延迟处理任务OS_IntQTask(),(这两个函数都定义在ucosiii\source的os_int.c文件中)该任务处理中再调用OS_QPost()函数,结果就是OS_QPost()调用点由中断中转移到中断处理任务中,节省了关中断时间。延迟推送和中断机制不是这里讨论的重点,所以直接进入OS_QPost()函数:
void OS_QPost (OS_Q *p_q,
                void *p_void,
                OS_MSG_SIZE msg_size,
                OS_OPT opt,
                CPU_TS ts,
                OS_ERR *p_err)   /*入口参数与OS_QPost一样*/
{
OS_OBJ_QTY cnt;
    OS_OPT post_type;
    OS_PEND_LIST *p_pend_list;
    OS_PEND_DATA *p_pend_data;
    OS_PEND_DATA *p_pend_data_next;
    OS_TCB *p_tcb;
    CPU_SR_ALLOC();
    OS_CRITICAL_ENTER();
    p_pend_list = &p_q->PendList;   /*这里是找出该队列下的OS_PEND_LIST列表*/
if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) {
          /* 如果列表里显示等待的任务TCB数目为0,也就是没有任务pend该队列,就没必要查
              找相关的任务进行推送,直接把消息保存下来就好了*/
部分代码略。
/*那么就调用OS_MsgQPut,将消息存储到队列中的消息链表中*/
OS_MsgQPut(&p_q->MsgQ,
                   p_void,
                   msg_size,
                   post_type,
                   ts,
                   p_err);
        OS_CRITICAL_EXIT();  
        return;
    }
    /* 如果列表里显示等待的任务TCB数目不为0,也就是有任务正在pend该队列,就必须把消息推送给它,就会执行以下代码*/
cnt = 要推送的数量;代码略;
p_pend_data = p_pend_list->HeadPtr;  /*从p_pend_list里找出p_pend_data链表*/
while (cnt > 0u) {
        p_tcb = p_pend_data->TCBPtr;   /*从p_pend_data里找出等待的任务TCB*/
        p_pend_data_next = p_pend_data->NextPtr;
        OS_Post((OS_PEND_OBJ *)((void *)p_q),  /*推送到等待的任务TCB*/
                p_tcb,
                p_void,
                msg_size,
                ts);
        p_pend_data = p_pend_data_next;   
        cnt--;    /*按要推送的数量cnt循环,直到退出*/
    }
OS_CRITICAL_EXIT_NO_SCHED();
    if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
        OSSched(); /* 进行任务调度   */
    }
   *p_err = OS_ERR_NONE;
}
可见,OS_QPost 函数中又包含了两层调用:如果没有任务等待该消息队列,就调用OS_MsgQPut函数;如果有任务在等待,就调用OS_Post把消息推送给正在等待的任务。
简单介绍下这两个函数,它们是最后一级了,内容基本都是查找排序算法,没有太多的架构知识可讲了:
OS_MsgQPut函数(定义在ucosiii\source的OS_msg.c中)负责从OS_MSG_POOL中取出一个空闲的OS_MSG,将消息写入到它内部,然后将该OS_MSG挂到对应的消息队列下面。
OS_Post函数(定义在ucosiii\source的OS_core.c中)是直接向任务推送消息的函数,它先判断任务是单队列QPend还是MultiPend:
如果是单队列QPend,就把消息内容指针直接写到TCB里面MsgPtr和MsgSize中:
p_tcb->MsgPtr = p_void; /* Deposit message in OS_TCB of task waiting */
p_tcb->MsgSize = msg_size;
注意这两个成员变量,是定义在任务TCB结构体中的两个成员,是伴随TCB一生的,可以随时取用。
如果是MultiPend,则调用OS_Post1函数,把消息内容指针写到OS_PEND_DATA中专供MultiPend使用的几个字段中,这个在前面介绍OS_PEND_DATA时有介绍,可以回头去再看一下。写入代码如下:
p_pend_data->RdyObjPtr = p_obj;
            p_pend_data->RdyMsgPtr = p_void;
            p_pend_data->RdyMsgSize = msg_size;
            p_pend_data->RdyTS = ts;
继承事业,薪火相传
返回列表