欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

LwIP之定时事件

发布时间:2025/3/15 编程问答 40 豆豆
生活随笔 收集整理的这篇文章主要介绍了 LwIP之定时事件 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

先看一下定时事件数据结构

/* 定时回调函数指针 */ 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); }

 

总结

以上是生活随笔为你收集整理的LwIP之定时事件的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。