LwIP之定时事件
程序员文章站
2024-02-22 18:31:58
...
先看一下定时事件数据结构
/* 定时回调函数指针 */
typedef void (*sys_timeout_handler)(void *arg);
/* 定时器事件 */
struct sys_timeo
{
struct sys_timeo *next; //下一个定时事件
u32_t time; //定时时间
sys_timeout_handler h; //定时回调函数
void *arg; //定时回调参数
};
所有的定时事件最终被串接在一个链表上
/* 定时事件队列 */
static struct sys_timeo *next_timeout;
下面看一下定时机制的实现代码
/* 初始化定时事件 */
void sys_timeouts_init(void)
{
/* 启动IP重组定时事件 */
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
/* 启动ARP定时事件 */
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
/* 启动定时事件 */
void sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
{
struct sys_timeo *timeout, *t;
/* 为定时事件结构体申请空间 */
timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
if(timeout == NULL)
{
return;
}
/* 初始化参数 */
timeout->next = NULL;
timeout->h = handler;
timeout->arg = arg;
timeout->time = msecs;
/* 定时事件队列为空 */
if(next_timeout == NULL)
{
next_timeout = timeout;
return;
}
/* 将定时事件插入链表 */
if(next_timeout->time > msecs)
{
next_timeout->time -= msecs;
timeout->next = next_timeout;
next_timeout = timeout;
}
else
{
for(t = next_timeout; t != NULL; t = t->next)
{
timeout->time -= t->time;
if(t->next == NULL || t->next->time > timeout->time)
{
if(t->next != NULL)
{
t->next->time -= timeout->time;
}
timeout->next = t->next;
t->next = timeout;
break;
}
}
}
}
/* 取消定时事件 */
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;
}
if(t->next != NULL)
{
t->next->time += t->time;
}
memp_free(MEMP_SYS_TIMEOUT, t);
return;
}
}
return;
}
/* 等待最早的事件超时或者等待邮箱消息 */
void sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
{
u32_t time_needed;
struct sys_timeo *tmptimeout;
sys_timeout_handler handler;
void *arg;
again:
/* 没有定时事件 */
if(!next_timeout)
{
time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
}
/* 有定时事件 */
else
{
/* 等待邮箱消息 */
if(next_timeout->time > 0)
{
time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
}
else
{
time_needed = SYS_ARCH_TIMEOUT;
}
/* 接收超时 */
if(time_needed == SYS_ARCH_TIMEOUT)
{
/* 删除定时事件 */
tmptimeout = next_timeout;
next_timeout = tmptimeout->next;
handler = tmptimeout->h;
arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
/* 调用定时事件 */
if(handler != NULL)
{
LOCK_TCPIP_CORE();
handler(arg);
UNLOCK_TCPIP_CORE();
}
LWIP_TCPIP_THREAD_ALIVE();
goto again;
}
/* 接收到邮箱消息 */
else
{
/* 更新定时事件 */
if(time_needed < next_timeout->time)
{
next_timeout->time -= time_needed;
}
else
{
next_timeout->time = 0;
}
}
}
}
最后看一下协议栈中的几个定时事件
/* TCP定时器活跃标志位 */
static int tcpip_tcp_timer_active;
/* TCP定时事件回调函数 */
static void tcpip_tcp_timer(void *arg)
{
/* TCP定时器回调函数(周期250ms) */
tcp_tmr();
/* 存在活跃(正在交互)的TCP控制块 */
/* 或存在等待2MSL状态的TCP控制块 */
if(tcp_active_pcbs || tcp_tw_pcbs)
{
/* 再次启动定时事件 */
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
}
else
{
tcpip_tcp_timer_active = 0;
}
}
/* 根据条件启动TCP定时事件 */
void tcp_timer_needed(void)
{
/* TCP定时事件未启动 */
/* 存在活跃(正在交互)的TCP控制块 */
/* 或存在等待2MSL状态的TCP控制块 */
if(!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs))
{
/* 启动TCP定时事件 */
tcpip_tcp_timer_active = 1;
sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
}
}
/* IP重组定时事件回调函数 */
static void ip_reass_timer(void *arg)
{
/* 重组IP数据报定时器回调函数(周期1秒) */
ip_reass_tmr();
/* 启动IP重组定时事件 */
sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
}
/* ARP定时事件回调函数 */
static void arp_timer(void *arg)
{
/* ARP定时器回调函数(周期5秒) */
etharp_tmr();
/* 启动ARP定时事件 */
sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
}
下一篇: c#的params参数使用示例