那个马蜂佬,刚发就给我两个赞
lwIP超时事件处理简介
为每个与外界网络连接的任务都设定了timeout属性,即等待超时时间,例如TCP建立连接超时、ARP缓存表项的时间管理等,都需要超时操作来处理
lwIP超时事件机制 一共有四种
2.1,超时事件如何管理
2.2,超时事件如何注册 增
2.3,超时事件如何删除 删
2.4,超时事件如何查询 查
LWIP超时事件结构体
typedef void (* lwip_cyclic_timer_handler)(void);
struct lwip_cyclic_timer
{
u32_t interval_ms; /* 超时时间 */
lwip_cyclic_timer_handler handler; /* 超时处理函数 */
};
LWIP超时管理结构体
typedef void (* sys_timeout_handler)(void *arg);
struct sys_timeo
{
struct sys_timeo *next; /* 下一个超时事件的指针 */
u32_t time; /* 当前超时事件的等待时间 */
sys_timeout_handler h; /* 指向超时的回调函数 */
void *arg; /* 超时的回调函数形数 */
};
超时事件注册
void sys_timeouts_init(void)
{
size_t i; /* 遍历轮询超时事件数组 */
for (i = (LWIP_TCP ? 1 : 0); i < LWIP_ARRAYSIZE(lwip_cyclic_timers); i++)
{
/* 注册超时事件 */
sys_timeout(lwip_cyclic_timers[i].interval_ms, lwip_cyclic_timer,
LWIP_CONST_CAST(void *, &lwip_cyclic_timers[i]));
}
}
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=%p\n",
(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;
}
}
}
}
next:下一个超时事件的指针
time:当前超时事件的等待时间
h:指向超时的回调函数
arg:超时的回调函数形数
PS:注意arg0 是第一个超时事件 next_timeout是程序的一个临时变量
超时事件如何删除
void sys_untimeout(sys_timeout_handler handler, void *arg)
{
struct sys_timeo *prev_t, *t;
if (next_timeout == NULL)
{ return; }
/* 从链表头开始遍历这个链表 */
for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next){
/* 查找删除的超时事件,判断超时事件的回调函数与函数参数释放一致 */
if ((t->h == handler) && (t->arg == arg))
{
if (prev_t == NULL) {
next_timeout = t->next; }
else {
prev_t->next = t->next; }
memp_free(MEMP_SYS_TIMEOUT, t); return;
}
}
return; }
把删除的事前的后一个事件指向 删除事件的前一个事件
超时事件如何查询
timeouts.c
Middlewares\lwip\src\core\timeouts.c
超时事件数组定义
每一个宏都是该协议的超时事件的使能
参考 : LWIP超时事件结构体
/** This array contains all stack-internal cyclic timers. To get the number of
* timers, use LWIP_ARRAYSIZE() */
const struct lwip_cyclic_timer lwip_cyclic_timers[] = {
#if LWIP_TCP
/* The TCP timer is a special case: it does not have to run always and
is triggered to start from TCP using tcp_timer_needed() */
{TCP_TMR_INTERVAL, HANDLER(tcp_tmr)},
#endif /* LWIP_TCP */
#if LWIP_IPV4
#if IP_REASSEMBLY
{IP_TMR_INTERVAL, HANDLER(ip_reass_tmr)},
#endif /* IP_REASSEMBLY */
#if LWIP_ARP
{ARP_TMR_INTERVAL, HANDLER(etharp_tmr)},
#endif /* LWIP_ARP */
#if LWIP_DHCP
{DHCP_COARSE_TIMER_MSECS, HANDLER(dhcp_coarse_tmr)},
{DHCP_FINE_TIMER_MSECS, HANDLER(dhcp_fine_tmr)},
#endif /* LWIP_DHCP */
#if LWIP_AUTOIP
{AUTOIP_TMR_INTERVAL, HANDLER(autoip_tmr)},
#endif /* LWIP_AUTOIP */
#if LWIP_IGMP
{IGMP_TMR_INTERVAL, HANDLER(igmp_tmr)},
#endif /* LWIP_IGMP */
#endif /* LWIP_IPV4 */
#if LWIP_DNS
{DNS_TMR_INTERVAL, HANDLER(dns_tmr)},
#endif /* LWIP_DNS */
#if LWIP_IPV6
{ND6_TMR_INTERVAL, HANDLER(nd6_tmr)},
#if LWIP_IPV6_REASS
{IP6_REASS_TMR_INTERVAL, HANDLER(ip6_reass_tmr)},
#endif /* LWIP_IPV6_REASS */
#if LWIP_IPV6_MLD
{MLD6_TMR_INTERVAL, HANDLER(mld6_tmr)},
#endif /* LWIP_IPV6_MLD */
#if LWIP_IPV6_DHCP6
{DHCP6_TIMER_MSECS, HANDLER(dhcp6_tmr)},
#endif /* LWIP_IPV6_DHCP6 */
#endif /* LWIP_IPV6 */
};