struct timer {
clock_time_t start;
clock_time_t interval;
};
RAW_U32 clock_time()
{
return raw_tick_count;
}
void
timer_set(struct timer *t, clock_time_t interval)
{
t->interval = interval;
t->start = clock_time();
}
void
timer_reset(struct timer *t)
{
t->start += t->interval;
}
void
timer_restart(struct timer *t)
{
t->start = clock_time();
}
int
timer_expired(struct timer *t)
{
return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
}
在主循环里初始化的时:
while(1) {
uip_len = tapdev_read();
if(uip_len > 0) {
if(BUF->type == htons(UIP_ETHTYPE_IP)) {
uip_arp_ipin();
uip_input();
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0) {
uip_arp_out();
tapdev_send();
}
} else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {
uip_arp_arpin();
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0) {
tapdev_send();
}
}
} else if(timer_expired(&periodic_timer)) {
timer_reset(&periodic_timer);
for(i = 0; i < UIP_CONNS; i++) {
uip_periodic(i);
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0) {
uip_arp_out();
tapdev_send();
}
}
#if UIP_UDP
for(i = 0; i < UIP_UDP_CONNS; i++) {
uip_udp_periodic(i);
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0) {
uip_arp_out();
tapdev_send();
}
}
#endif /* UIP_UDP */
/* Call the ARP timer function every 10 seconds. */
if(timer_expired(&arp_timer)) {
timer_reset(&arp_timer);
uip_arp_timer();
}
}
}
return 0;
}
struct timer periodic_timer, arp_timer;
timer_set(&periodic_timer, CLOCK_SECOND / 2);
timer_set(&arp_timer, CLOCK_SECOND * 10);
periodic_timer->start=xxxx (这个值是当系统tick递增之后的某个确定值)
periodic_timer-> interval=50 (这是时间间隔 50个滴答,相当于 500ms)
在whlie(1)里面 先看看有没有数据包到来,最多花费20个tick,
有数据包,就处理,没有数据包,就判断是否
else if(timer_expired(&periodic_timer)) {
timer_reset(&periodic_timer);
for(i = 0; i < UIP_CONNS; i++) {
uip_periodic(i);
/* If the above function invocation resulted in data that
should be sent out on the network, the global variable
uip_len is set to a value > 0. */
if(uip_len > 0) {
uip_arp_out();
tapdev_send();
}
上面是判断,自上次重置定时器后是否已经500了,如果已经到了,则再次重置定时器触发事件,
periodic_timer->start=xxxx (这个值是当系统tick)
periodic_timer-> interval=50 (这是时间间隔 50个滴答,相当于 500ms)
到了之后,就会当前的所有连接经行uip_periodic, 其实就是把所有的连接都再执行一遍,根据里面的标志位和uip-conn->timer-- 来判断是否有超时数据需要重传。
再下面就是关于UDP 和 ARP 的处理,由于UDP不能主动发送数据,所以在每次轮训的时候,看每个UDP连接是否有数据需要发送,有就发送出去,没有就不发送, timer_set(&periodic_timer, CLOCK_SECOND / 2);这句代码决定了UDP的发送速率,由于设置的时间间隔的关系,吞吐量已经确定袭来了,如果想提高吞吐量,可以将时间的间隔减小,系统的吞吐量就会提高了,不过这样系统的负载家中了,因为执行了很多无用代码。
这个软定时器的本质就是根据tick,设置下它本次应该终止的时间,利用
timer_expired
timer_expired(struct timer *t)
{
return (clock_time_t)(clock_time() - t->start) >= (clock_time_t)t->interval;
}
来判断是否已经到达了,自己设置的时间间隔。