欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;

LwIP之定时事件

 

下面看一下定时机制的实现代码

/* 初始化定时事件 */
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