我是靠谱客的博主 无聊项链,最近开发中收集的这篇文章主要介绍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.c
和timeouts.h
中。
2.定时器机制
timeouts.h
中定义定时器的结构——sys_timeo
,其中包含下一个定时器指针,当前定时器时间,超时处理函数timeouts.c
中定义全局链表变量next_timeout
,也就是定时器链表头。- 通过
timeouts.c
中的sys_timeout
函数(实际是sys_timeout_abs
函数)向next_timeout
添加一个定时的sys_timeo
- 当调用
sys_timeouts_mbox_fetch()
或者sys_check_timeouts()
(NO_SYS==1 only)时会进行超时的检查及处理 - 通过
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.定时器与超时处理参考所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复