我是靠谱客的博主 无聊项链,最近开发中收集的这篇文章主要介绍LWIP——超时处理(定时器)1.使用超时处理的目的2.定时器机制3. 定时器结构4. 定时器的添加5. 定时器检查及超时操作6. 周期定时器7.定时器与超时处理参考,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

LWIP——超时处理

  • 1.使用超时处理的目的
  • 2.定时器机制
  • 3. 定时器结构
  • 4. 定时器的添加
  • 5. 定时器检查及超时操作
  • 6. 周期定时器
  • 7.定时器与超时处理
  • 参考

1.使用超时处理的目的

  • 旧版本中LWIP称之为定时器并用timer.c来实现定时器的功能,迭代版本中更改为超时处理,更名后,虽然处理结果基本一致,但在实现上却可以看出两种命名之下的区别,在**“7.定时器与超时处理”**小节中简要分析。
  • LWIP中为什么需要做超时处理呢,这可从其实现的TCP/IP栈功能即可得知,TCP中的建立连接超时、重传超时机制IP分片数据报的重装等待超时ARP缓存表项的时间管理ping接收数据包超时处理等等,都需要使用超时操作来处理。
  • LWIP超时操作代码主要在timeouts.ctimeouts.h中。

2.定时器机制

  1. timeouts.h中定义定时器的结构——sys_timeo,其中包含下一个定时器指针当前定时器时间超时处理函数
  2. timeouts.c中定义全局链表变量next_timeout,也就是定时器链表头。
  3. 通过timeouts.c中的sys_timeout函数(实际是sys_timeout_abs函数)向next_timeout添加一个定时的sys_timeo
  4. 当调用sys_timeouts_mbox_fetch()或者sys_check_timeouts() (NO_SYS==1 only)时会进行超时的检查及处理
  5. 通过sys_untimeout(sys_timeout_handler handler, void *arg)函数可删除定时器,由入参可知,handler处理函数和对应的入参arg是定时器的唯一标识

3. 定时器结构

定时器结构体定义
srcincludelwiptimeouts.h

struct sys_timeo {
  struct sys_timeo *next;  //(1)
  u32_t time;              //(2)
  sys_timeout_handler h;   //(3)
  void *arg;               //(4)
#if LWIP_DEBUG_TIMERNAMES
  const char* handler_name;//(5)
#endif /* LWIP_DEBUG_TIMERNAMES */
};

(1)指向下一个超时计时结构体
(2)时间(ms)
(3)超时回调函数
(4)超时回调函数入参
(5)超时计时器名称,用于DEBUG情况下使用

4. 定时器的添加

/**
 * Create a one-shot timer (aka timeout). Timeouts are processed in the
 * following cases:
 * - while waiting for a message using sys_timeouts_mbox_fetch()
 * - by calling sys_check_timeouts() (NO_SYS==1 only)
 *
 * @param msecs time in milliseconds after that the timer should expire
 * @param handler callback function to call when msecs have elapsed
 * @param arg argument to pass to the callback function
 */
#if LWIP_DEBUG_TIMERNAMES
void
sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char *handler_name)
#else /* LWIP_DEBUG_TIMERNAMES */
void
sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
#endif /* LWIP_DEBUG_TIMERNAMES */
{
  u32_t next_timeout_time;

  LWIP_ASSERT_CORE_LOCKED();

  LWIP_ASSERT("Timeout time too long, max is LWIP_UINT32_MAX/4 msecs", msecs <= (LWIP_UINT32_MAX / 4));

  next_timeout_time = (u32_t)(sys_now() + msecs); /* overflow handled by TIME_LESS_THAN macro */ 

#if LWIP_DEBUG_TIMERNAMES
  sys_timeout_abs(next_timeout_time, handler, arg, handler_name);
#else
  sys_timeout_abs(next_timeout_time, handler, arg);
#endif
}
static void
#if LWIP_DEBUG_TIMERNAMES
sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg, const char *handler_name)
#else /* LWIP_DEBUG_TIMERNAMES */
sys_timeout_abs(u32_t abs_time, sys_timeout_handler handler, void *arg)
#endif
{
  struct sys_timeo *timeout, *t;

  timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
  if (timeout == NULL) {
    LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
    return;
  }

  timeout->next = NULL;
  timeout->h = handler;
  timeout->arg = arg;
  timeout->time = abs_time;

#if LWIP_DEBUG_TIMERNAMES
  timeout->handler_name = handler_name;
  LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p abs_time=%"U32_F" handler=%s arg=%pn",
                             (void *)timeout, abs_time, handler_name, (void *)arg));
#endif /* LWIP_DEBUG_TIMERNAMES */

  if (next_timeout == NULL) {
    next_timeout = timeout;
    return;
  }
  if (TIME_LESS_THAN(timeout->time, next_timeout->time)) {
    timeout->next = next_timeout;
    next_timeout = timeout;
  } else {
    for (t = next_timeout; t != NULL; t = t->next) {
      if ((t->next == NULL) || TIME_LESS_THAN(timeout->time, t->next->time)) {
        timeout->next = t->next;
        t->next = timeout;
        break;
      }
    }
  }
}

从0开始依次添加三个超时操作,时间分别是20ms,10ms,50ms,添加过程如下示意图
在这里插入图片描述
实际代码验证

sys_timeout(10, callback_function, NULL);  // callback_function可以随便写一个函数
sys_timeout(50, callback_function, NULL);
sys_timeout(10, callback_function, NULL);
sys_timeout(150, callback_function, NULL);
sys_timeout(20, callback_function, NULL);

// #define LWIP_TESTMODE 1 // do this in lwipopts.h
struct sys_timeo *timer_head = sys_timeouts_get_next_timeout();
while(timer_head->next != NULL)
{
	printf("sys_timeout %dn", timer_head->time);
}
/** output:
 * sys_timeout 10
 * sys_timeout 10
 * sys_timeout 20
 * sys_timeout 50
 * sys_timeout 100
 * sys_timeout 150
 */

5. 定时器检查及超时操作

/**
 * @ingroup lwip_nosys
 * Handle timeouts for NO_SYS==1 (i.e. without using
 * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
 * handler functions when timeouts expire.
 *
 * Must be called periodically from your main loop.
 */
void
sys_check_timeouts(void)
{
  u32_t now;

  LWIP_ASSERT_CORE_LOCKED();

  /* Process only timers expired at the start of the function. */
  now = sys_now();

  do {
    struct sys_timeo *tmptimeout;
    sys_timeout_handler handler;
    void *arg;

    PBUF_CHECK_FREE_OOSEQ();

    tmptimeout = next_timeout;
    if (tmptimeout == NULL) {
      return;
    }

    if (TIME_LESS_THAN(now, tmptimeout->time)) {
      return;
    }

    /* Timeout has expired */
    next_timeout = tmptimeout->next;
    handler = tmptimeout->h;
    arg = tmptimeout->arg;
    current_timeout_due_time = tmptimeout->time;
#if LWIP_DEBUG_TIMERNAMES
    if (handler != NULL) {
      LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s t=%"U32_F" arg=%pn",
                                 tmptimeout->handler_name, sys_now() - tmptimeout->time, arg));
    }
#endif /* LWIP_DEBUG_TIMERNAMES */
    memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
    if (handler != NULL) {
      handler(arg);
    }
    LWIP_TCPIP_THREAD_ALIVE();

    /* Repeat until all expired timers have been called */
  } while (1);
}

6. 周期定时器

7.定时器与超时处理

参考

  • https://www.nongnu.org/lwip/2_1_x/timeouts_8c.html
  • https://www.kancloud.cn/jiejietop/tcpip/988572
  • https://mail.gnu.org/archive/html/lwip-users/2021-05/msg00024.html
  • https://blog.csdn.net/ZCShouCSDN/article/details/80271231
  • https://blog.csdn.net/everysmile/article/details/51184331
  • http://blog.chinaunix.net/uid-29074210-id-4836313.html
  • https://blog.csdn.net/m0_37621078/article/details/97978998
  • https://www.jianshu.com/p/f9f333edeb13

最后

以上就是无聊项链为你收集整理的LWIP——超时处理(定时器)1.使用超时处理的目的2.定时器机制3. 定时器结构4. 定时器的添加5. 定时器检查及超时操作6. 周期定时器7.定时器与超时处理参考的全部内容,希望文章能够帮你解决LWIP——超时处理(定时器)1.使用超时处理的目的2.定时器机制3. 定时器结构4. 定时器的添加5. 定时器检查及超时操作6. 周期定时器7.定时器与超时处理参考所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部