os_mbox.c

本文介绍了uCOS-II操作系统中消息邮箱的实现原理与使用方法,包括创建、发送、接收等核心函数的功能与流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  定位到uCOS-II/Source/os_mbox.c,该文件是消息邮箱管理的相关操作函数。

  任务与任务之间需要数据传递,那么为了适应传递的数据的不同类型,可以建立一个缓冲区(void*类型可以接收不同类型的数据),然后以该缓冲区为介质来实现任务间的切换,这就是消息邮箱的数据传输原理。

  消息邮箱的具体实现是:将数据缓冲区的指针赋给事件控制块(OS_EVENT)的成员OSEventPtr(OSEventPtr是个void* 类型),同时设置OSEventPtr中的用于表示事件类型的成员OSEventType为OS_EVENT_TYPE_MBOX。

1. 查看邮箱是否有需要的消息函数OSMboxAccept()

  OSMboxAccept()是非阻塞的,和OSMboxPend()函数不同(在下面解析)。OSMboxAccept()会从消息邮箱中试图取出消息,若没有消息可取,OSMboxAccept()函数并不挂起任务。若有消息可提取,则OSMboxAccept()函数提取消息完毕后会将该邮箱中存放消息的位置清空。因为该函数是非阻塞的,所以它允许在ISR中被调用。

#if OS_MBOX_ACCEPT_EN > 0u
void  *OSMboxAccept (OS_EVENT *pevent)
{
    void      *pmsg;
#if OS_CRITICAL_METHOD == 3u 
    OS_CPU_SR  cpu_sr = 0u;
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        return ((void *)0);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { //pevent类型检查
        return ((void *)0);
    }
    OS_ENTER_CRITICAL();
    pmsg               = pevent->OSEventPtr;    //取出消息中的内容
    pevent->OSEventPtr = (void *)0;
    OS_EXIT_CRITICAL();     //取出后将其清空
    return (pmsg);   
}
#endif

2. 创建一个邮箱函数OSMboxCreate()

  OSMboxCreate()函数用于建立并初始化一个邮箱信息,参数是消息指针,返回值是消息邮箱的指针。

OS_EVENT  *OSMboxCreate (void *pmsg)
{
    OS_EVENT  *pevent;
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif

#ifdef OS_SAFETY_CRITICAL_IEC61508
    if (OSSafetyCriticalStartFlag == OS_TRUE) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return ((OS_EVENT *)0);
    }
#endif

    if (OSIntNesting > 0u) {
        return ((OS_EVENT *)0);
    }
    OS_ENTER_CRITICAL();

    //取出空闲事件节点 
    pevent = OSEventFreeList;
    if (OSEventFreeList != (OS_EVENT *)0) {
        //全局变量OSEventFreeList指向下一个空闲事件节点
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    //初始化该空闲事件节点为消息邮箱的相关设置
    if (pevent != (OS_EVENT *)0) {
        pevent->OSEventType    = OS_EVENT_TYPE_MBOX;
        pevent->OSEventCnt     = 0u;    //其实对mbox来说此参数没用
        pevent->OSEventPtr     = pmsg;
#if OS_EVENT_NAME_EN > 0u
        pevent->OSEventName    = (INT8U *)(void *)"?";
#endif
        OS_EventWaitListInit(pevent);   //定义在os_core.c中,置空该事件的等待队列
    }
    return (pevent); 
}

  任务调用OSMboxCreate()时一般其参数msg为NULL,也可以事先定义一个邮箱,然后将该邮箱内的消息指针传递给OSMboxCreate()函数的msg,从而使得新建的邮箱从一开始就指代一个邮箱。

3. 删除邮箱函数OSMboxDel()

  删除消息邮箱,因为其他任务可能处于等待获取该消息邮箱,所以在删除之前应该要安置好这些等待任务。

#if OS_MBOX_DEL_EN > 0u
OS_EVENT  *OSMboxDel (OS_EVENT  *pevent,    //指定邮箱
                      INT8U      opt,       //删除操作选项
                      INT8U     *perr)      //输出型参数,用于指定出错信息
{
    BOOLEAN    tasks_waiting;
    OS_EVENT  *pevent_return;
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif

#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return ((OS_EVENT *)0);
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        *perr = OS_ERR_PEVENT_NULL;
        return (pevent);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
        *perr = OS_ERR_EVENT_TYPE;
        return (pevent);
    }
    if (OSIntNesting > 0u) {
        *perr = OS_ERR_DEL_ISR;
        return (pevent);
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0u) { //有任务在阻塞等待该MBox上的消息
        tasks_waiting = OS_TRUE;    //Yes
    } else {
        tasks_waiting = OS_FALSE;   //No
    }
    switch (opt) {
        case OS_DEL_NO_PEND:    //opt等于OS_DEL_NO_PEND表示无任务在等待才删除该Mbox
             if (tasks_waiting == OS_FALSE) {   //无任务等待
#if OS_EVENT_NAME_EN > 0u
                 pevent->OSEventName = (INT8U *)(void *)"?";
#endif
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED; //设置事件为空闲状态
                 pevent->OSEventPtr  = OSEventFreeList;      //OSEventFreeList原先是指向具体消息的,现指向下一个空闲事件节点
                 pevent->OSEventCnt  = 0u;                   //计数器,Mbox没用处
                 OSEventFreeList     = pevent;
                 OS_EXIT_CRITICAL();
                 *perr               = OS_ERR_NONE;
                 pevent_return       = (OS_EVENT *)0;
             } else {   //有任务等待,出错返回
                 OS_EXIT_CRITICAL();
                 *perr               = OS_ERR_TASK_WAITING;
                 pevent_return       = pevent;
             }
             break;

        case OS_DEL_ALWAYS:     //尽管有任务在等待还是要删除
             while (pevent->OSEventGrp != 0u) {  //有任务在等待,先逐一置为Rdy状态
                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
             }
#if OS_EVENT_NAME_EN > 0u
             pevent->OSEventName    = (INT8U *)(void *)"?";
#endif
             //一样的删除操作
             pevent->OSEventType    = OS_EVENT_TYPE_UNUSED;
             pevent->OSEventPtr     = OSEventFreeList;
             pevent->OSEventCnt     = 0u;
             OSEventFreeList        = pevent; 
             OS_EXIT_CRITICAL();
             if (tasks_waiting == OS_TRUE) { 
                 OS_Sched();  //若系统已经在运行,发起调度
             }
             *perr         = OS_ERR_NONE;
             pevent_return = (OS_EVENT *)0;
             break;

        default:  //操作选项有误,出错返回
             OS_EXIT_CRITICAL();
             *perr         = OS_ERR_INVALID_OPT;
             pevent_return = pevent;
             break;
    }
    return (pevent_return);
}
#endif

4. 阻塞请求消息邮箱函数OSMboxPend()

  任务请求邮箱时调用OSMboxPend()函数,该函数是带阻塞的:查看邮箱内存放消息的指针OSEventPtr是否为NULL,若不为NULL则将邮箱中的消息指针返回给调用者,若为NULL则使任务进入挂起状态,并会引发调度。

void  *OSMboxPend (OS_EVENT  *pevent,    //指定MBox
                   INT32U     timeout,   //超时时间设置
                   INT8U     *perr)
{
    void      *pmsg;
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif

#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return ((void *)0);
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        *perr = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
        *perr = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    if (OSIntNesting > 0u) {
        *perr = OS_ERR_PEND_ISR;
        return ((void *)0);
    }
    if (OSLockNesting > 0u) {
        *perr = OS_ERR_PEND_LOCKED;
        return ((void *)0);
    }
    OS_ENTER_CRITICAL();
    pmsg = pevent->OSEventPtr;      //取出邮箱内的消息
    if (pmsg != (void *)0) {        //邮箱中的消息不为NULL
        pevent->OSEventPtr = (void *)0; //读取完毕后清空该消息指针
        OS_EXIT_CRITICAL();
        *perr = OS_ERR_NONE;
        return (pmsg);
    }

    //执行到这里说明邮箱内的消息为空,需要阻塞
    OSTCBCur->OSTCBStat     |= OS_STAT_MBOX;        //进入等待消息邮箱状态,表只能通过消息邮箱唤醒  
    OSTCBCur->OSTCBStatPend  = OS_STAT_PEND_OK;     //挂起
    OSTCBCur->OSTCBDly       = timeout;             //超时时间
    OS_EventTaskWait(pevent);                       //定义在os_core.c中,将自身添加到事件等待列表中
    OS_EXIT_CRITICAL();
    OS_Sched();                                     //重新调度,调度后会有一个优先级比当前优先级低的任务得到执行
                                                    //而当前任务在等待有任务向Mbox发消息
    OS_ENTER_CRITICAL();

    //能执行到这里,说明其他任务:
    //a. 调用了OSMboxPostOpt()释放该Mbox
    //b. 调用OSMboxDel()、OSMboxPendAbort()删除了该Mbox
    //c. 等待超时
    switch (OSTCBCur->OSTCBStatPend) {
        case OS_STAT_PEND_OK:   //有任务调用了OSMboxPostOpt进而唤醒当前任务
             pmsg =  OSTCBCur->OSTCBMsg;  //提取任务的消息指针
            *perr =  OS_ERR_NONE;
             break;

        case OS_STAT_PEND_ABORT:    //MBox被删除了
             pmsg = (void *)0;
            *perr =  OS_ERR_PEND_ABORT;
             break;

        case OS_STAT_PEND_TO:       //超时,不再等待
        default:
             OS_EventTaskRemove(OSTCBCur, pevent);  //定义在os_core.c中,将当前任务从event等待列表中清除
             pmsg = (void *)0;
            *perr =  OS_ERR_TIMEOUT; 
             break;
    }

    //设置任务状态
    OSTCBCur->OSTCBStat          =  OS_STAT_RDY; 
    OSTCBCur->OSTCBStatPend      =  OS_STAT_PEND_OK;
    OSTCBCur->OSTCBEventPtr      = (OS_EVENT  *)0;
#if (OS_EVENT_MULTI_EN > 0u)
    OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif
    OSTCBCur->OSTCBMsg           = (void      *)0; 
    OS_EXIT_CRITICAL();
    return (pmsg);
}

  在超时时间范围内收到消息后,任务是通过”OSTCBCur->OSTCBMsg”提取消息并继续执行的,为什么不是”pevent->OSEventPtr”提取?
  这是因为多任务消息传递时可以将消息直接赋给各个任务的TCB的OSTCBMsg成员。

5. 唤醒等待消息邮箱的任务函数OSMboxPendAbort()

  其实这个函数并非pend(获取),而是类似post(释放)MBox,具体实现唤醒单个/所有等待任务。

#if OS_MBOX_PEND_ABORT_EN > 0u
INT8U  OSMboxPendAbort (OS_EVENT  *pevent,
                        INT8U      opt,
                        INT8U     *perr)
{
    INT8U      nbr_tasks;       //用于记录有多少个任务在等待该事件(Mbox)
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif

#ifdef OS_SAFETY_CRITICAL
    if (perr == (INT8U *)0) {
        OS_SAFETY_CRITICAL_EXCEPTION();
        return (0u);
    }
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        *perr = OS_ERR_PEVENT_NULL;
        return (0u);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
        *perr = OS_ERR_EVENT_TYPE;
        return (0u);
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0u) {  //有任务在等待
        nbr_tasks = 0u;
        switch (opt) {
            case OS_PEND_OPT_BROADCAST:  //广播,唤醒所有在等待的任务
                 while (pevent->OSEventGrp != 0u) {
                     (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
                     nbr_tasks++;
                 }
                 break;

            case OS_PEND_OPT_NONE:      /只唤醒一个任务,即优先级最高的一个
            default:
                 (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
                 nbr_tasks++;
                 break;
        }
        OS_EXIT_CRITICAL();
        OS_Sched();1            //调度
        *perr = OS_ERR_PEND_ABORT;
        return (nbr_tasks);
    }
    OS_EXIT_CRITICAL();
    *perr = OS_ERR_NONE;
}
#endif

6. 向消息邮箱发送消息函数OSMboxPost()

  任务可以通过OSMboxPost()函数向目标消息邮箱发送消息,参数二为消息缓冲区的指针。

#if OS_MBOX_POST_EN > 0u
INT8U  OSMboxPost (OS_EVENT  *pevent,
                   void      *pmsg)
{
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        return (OS_ERR_PEVENT_NULL);
    }
    if (pmsg == (void *)0) {
        return (OS_ERR_POST_NULL_PTR);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
        return (OS_ERR_EVENT_TYPE);
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0u) {  //有任务在等待

        //唤醒等待任务中优先级最高的任务,并将消息填充到该任务的TCB的OSTCBMsg成员中
        (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
        OS_EXIT_CRITICAL();
        OS_Sched();         //调度
        return (OS_ERR_NONE);
    }

    //若消息邮箱中的消息指针已经存有数据,出错返回
    if (pevent->OSEventPtr != (void *)0) {
        OS_EXIT_CRITICAL();
        return (OS_ERR_MBOX_FULL);
    }

    //没任务等待且消息邮箱中的消息指针不为空,将pmsg赋给消息邮箱的消息指针
    pevent->OSEventPtr = pmsg; 
    OS_EXIT_CRITICAL();
    return (OS_ERR_NONE);
}
#endif

  这里需要注意,定义在OS_EventTaskRdy()的函数的具体实现并非将pmsg消息赋给消息邮箱的消息指针而是赋给最高优先级任务的TCB的OSTCBMsg成员,这就跟前面OSMboxPend()函数中提取消息操作”pmsg = OSTCBCur->OSTCBMsg”对应上了。

  由此可见,uCOS-II为了效率,还可以将数据赋给即将被调度运行的目标任务的TCB的OSTCBMsg成员。

7. 向邮箱发送消息的另一函数OSMboxPostOpt()

  OSMboxPostOpt()函数可以以广播的方式向MBox时间等待任务列表中的所有任务发送消息。

#if OS_MBOX_POST_OPT_EN > 0u
INT8U  OSMboxPostOpt (OS_EVENT  *pevent,
                      void      *pmsg,
                      INT8U      opt)
{
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR  cpu_sr = 0u;
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        return (OS_ERR_PEVENT_NULL);
    }
    if (pmsg == (void *)0) {
        return (OS_ERR_POST_NULL_PTR);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
        return (OS_ERR_EVENT_TYPE);
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0u) {
        if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { //含有OS_POST_OPT_BROADCAST操作选项
            while (pevent->OSEventGrp != 0u) { // 有任务在等待
                 //唤醒任务并将消息pmsg填充到该任务的TCB的OSTCBMsg中
                (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
            }
        } else {
            //唤醒单个任务,优先级最高的
            (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
        }
        OS_EXIT_CRITICAL();

        if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { //为0表示没有包含OS_POST_OPT_NO_SCHED操作选项
            OS_Sched();         //需要调度
        }
        return (OS_ERR_NONE);
    }

    //若消息邮箱中的消息指针已经存有数据,出错返回
    if (pevent->OSEventPtr != (void *)0) { 
        OS_EXIT_CRITICAL();
        return (OS_ERR_MBOX_FULL);
    }

    //没任务等待且消息邮箱中的消息指针不为空,将pmsg赋给消息邮箱的消息指针
    pevent->OSEventPtr = pmsg;
    OS_EXIT_CRITICAL();
    return (OS_ERR_NONE);
}
#endif

8. 查询邮箱状态函数OSMboxQuery()

  OSMboxQuery()可用于查看MBox的状态,其状态信息保存在函数的输入型参数p_mbox_data中,p_mbox_data为OS_MBOX_DATA类型的指针,OS_MBOX_DATA原型为:

typedef struct os_mbox_data {
    void   *OSMsg;                          //消息邮箱的有效信息

    //任务等待列表,存放等待该MBox的所有任务
#if OS_LOWEST_PRIO <= 63
    INT8U   OSEventTbl[OS_EVENT_TBL_SIZE];
    INT8U   OSEventGrp;
#else
    INT16U  OSEventTbl[OS_EVENT_TBL_SIZE];
    INT16U  OSEventGrp; 
#endif
} OS_MBOX_DATA;

  函数原型为:

#if OS_MBOX_QUERY_EN > 0u
INT8U  OSMboxQuery (OS_EVENT      *pevent,
                    OS_MBOX_DATA  *p_mbox_data)
{
    INT8U       i;
    OS_PRIO    *psrc;
    OS_PRIO    *pdest;
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR   cpu_sr = 0u;
#endif

#if OS_ARG_CHK_EN > 0u
    if (pevent == (OS_EVENT *)0) {
        return (OS_ERR_PEVENT_NULL);
    }
    if (p_mbox_data == (OS_MBOX_DATA *)0) {
        return (OS_ERR_PDATA_NULL);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {
        return (OS_ERR_EVENT_TYPE);
    }

    OS_ENTER_CRITICAL();
    p_mbox_data->OSEventGrp = pevent->OSEventGrp;

    //(等待任务)数组赋值,需要用for()语句逐一赋值
    psrc                    = &pevent->OSEventTbl[0];
    pdest                   = &p_mbox_data->OSEventTbl[0];
    for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
        *pdest++ = *psrc++;
    }
    p_mbox_data->OSMsg = pevent->OSEventPtr; 
    OS_EXIT_CRITICAL();
    return (OS_ERR_NONE);
}
#endif
<think>嗯,用户想了解LWIP中的tcpip_timeouts_mbox_fetch函数的具体信息。从用户提供的引用来看,ta对LWIP的定时器机制和线程交互有较深的理解需求,尤其是超时处理与邮箱等待的结合实现。用户引用的三段资料很有价值:1.引用[1]提到了ip_reass_tmr和sys_timeout的周期调用机制,特别指出tmr任务在sys_arch_sem_wait和sys_arch_mbox_wait时运作。这正好解释了超时处理与线程阻塞的关系。2.引用[2]虽然讲的是网卡发送,但说明用户关注底层实现细节。3.引用[3]直接涉及timeout结构体管理,强调sys_arch_timeouts需要用户根据OS实现,这对理解上下文很重要。这个函数名称有点特殊,标准LWIP里常见的是tcpip_thread中的mbox_fetch调用链。用户可能是看到定制化代码时产生的疑问,需要区分标准实现与扩展实现。准备这样解答:首先明确标准LWIP里通常没有tcpip_timeouts_mbox_fetch这个命名,可能是用户代码的封装函数。然后聚焦核心机制:tcpip_thread线程在sys_mbox_fetch等待期间处理超时任务。要拆解四点:1)线程阻塞时如何激活定时器检查2)sys_arch_timeouts的线程本地存储作用3)sys_arch_mbox_fetch内部处理流程4)超时任务处理完毕后的行为考虑到用户引用过sys_arch_timeouts的实现要求,特别强调"线程私有timeout队列"的概念。用$$包裹关键结构体定义展示会更清晰,比如timeout结构体包含next/msec/handler/arg字段。用户需要技术实现细节,所以可以描述线程控制块的OS层存储方案,比如nios_uc示例中通过OSTCBCur访问控制块,再取出timeout队列。对超时计算的while循环处理要说明时间差(remain-=residual)的精妙之处。最后提醒API变化风险:较新版本可能封装为tcpip_timeout/tcpip_untimeout。这样应该能覆盖用户需要的技术要点。</think> 根据引用资料中关于LwIP定时器和线程模型的关键技术点,结合标准LwIP实现原理,`tcpip_timeouts_mbox_fetch`(标准API通常为`sys_arch_mbox_fetch`)的实现细节和用法如下: ### 函数功能说明 该函数是LwIP**线程阻塞等待邮箱消息的核心机制**,在等待期间同步处理定时任务队列。主要行为: 1. **处理挂起的定时任务**:在等待邮箱消息前检查并执行所有到期超时任务 2. **动态调整阻塞时长**:根据最近定时任务的到期时间自动计算阻塞超时值 3. **消息队列监控**:监控指定邮箱消息到达情况 ```c /* 函数原型(典型实现) */ err_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout_ms) ``` ### 实现关键流程 1. **获取当前线程的timeout队列** 调用`sys_arch_timeouts()`获取当前线程关联的定时器链表(引用[3]): ```c struct sys_timeouts *timeouts = sys_arch_timeouts(); ``` 2. **计算有效等待时间** 动态计算最近到期任务的时间差作为实际阻塞时长: $$ \text{wait\_time} = \min(\text{timeout\_ms}, \text{next\_expiry\_delta}) $$ 3. **处理定时器链表** 按优先级顺序执行到期任务: ```c while(timeouts && timeouts->time <= now) { timeouts->handler(timeouts->arg); // 执行注册的回调函数 timeouts = timeouts->next; // 移至下一个定时节点 } ``` 4. **执行OS邮箱等待** 调用底层OS的阻塞等待接口(如信号量/邮箱),例如在FreeRTOS中: ```c xQueueReceive(mbox->q, msg, pdMS_TO_TICKS(wait_time)); ``` 5. **返回执行结果** - 若在`wait_time`内收到消息:返回`ERR_OK`并传递消息指针 - 若超时未收到消息:返回`SYS_ARCH_TIMEOUT` ### 函数特性 1. **线程私有性** 每个OS线程通过`sys_arch_timeouts()`维护独立的定时器队列(引用[3]),确保定时任务隔离执行。 2. **周期调度机制** 结合`sys_timeout(IP_TMR_INTERVAL, ...)`实现周期性系统任务(如IP分片重组引用[1])。 3. **阻塞中的超时处理** 当LWIP线程(如`tcpip_thread`)在邮箱等待时自动执行定时任务(引用[1])。 ### 应用场景 ```mermaid graph LR A[tcpip_thread] --> B{sys_mbox_fetch} B --> C[执行timeout任务] B --> D[邮箱消息等待] C --> E[IP分片重组<br/>ip_reass_tmr] C --> F[ARP缓存更新] C --> G[TCP状态机维护] ``` ### 注意事项 1. 该函数通常由LwIP内部线程(如`tcpip_thread`)自动调用 2. 用户自定义线程需通过`sys_thread_new()`创建以初始化定时器队列 3. 新增定时任务需调用`sys_timeout()`注册到当前线程队列 > **注**:实际函数名在不同版本可能差异,V2.1+版本使用`sys_mbox_fetch`,早期版本或定制实现可能采用`tcpip_timeouts_mbox_fetch`等别名[^1][^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值