解析lwIP的tcp_fasttmr
函数
1. 引言
在本篇博客中,我们将对lwIP(轻量级的IP)库中的tcp_fasttmr
函数进行详细剖析。lwIP是一个用于嵌入式系统的开源TCP/IP协议栈,其主要特点是对系统资源需求极小,能够与各种嵌入式系统配合使用。
这个函数被设计为处理由上层(应用)之前"拒绝"的数据,并在每个TCP_FAST_INTERVAL(250毫秒)发送延迟的ACK或挂起的FIN。它会自动从tcp_tmr()
被调用。
2. 函数代码
首先,我们来看一下tcp_fasttmr
函数的源代码:
void tcp_fasttmr(void)
{
struct tcp_pcb *pcb;
++tcp_timer_ctr;
tcp_fasttmr_start:
pcb = tcp_active_pcbs;
while (pcb != NULL) {
if (pcb->last_timer != tcp_timer_ctr) {
struct tcp_pcb *next;
pcb->last_timer = tcp_timer_ctr;
/* send delayed ACKs */
if (pcb->flags & TF_ACK_DELAY) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: delayed ACK\n"));
tcp_ack_now(pcb);
tcp_output(pcb);
tcp_clear_flags(pcb, TF_ACK_DELAY | TF_ACK_NOW);
}
/* send pending FIN */
if (pcb->flags & TF_CLOSEPEND) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_fasttmr: pending FIN\n"));
tcp_clear_flags(pcb, TF_CLOSEPEND);
tcp_close_shutdown_fin(pcb);
}
next = pcb->next;
/* If there is data which was previously "refused" by upper layer */
if (pcb->refused_data != NULL) {
tcp_active_pcbs_changed = 0;
tcp_process_refused_data(pcb);
if (tcp_active_pcbs_changed) {
/* application callback has changed the pcb list: restart the loop */
goto tcp_fasttmr_start;
}
}
pcb = next;
} else {
pcb = pcb->next;
}
}
}
3. 函数参数解析
tcp_fasttmr
函数没有参数,但是它使用了一些全局变量。让我们详细了解一下这些全局变量:
-
struct tcp_pcb *pcb;
:这是一个指向tcp_pcb结构的指针,用于描述一个TCP连接的状态。这个结构包含了许多字段,包括用于跟踪连接的各种状态(如超时,重试等)的标志,以及用于发送和接收数据的缓冲区等。 -
tcp_timer_ctr
:这个变量用于跟踪tcp_fasttmr函数被调用的次数。每当函数被调用时,就会使这个计数器加一。
4. 函数逻辑解析
函数的主要逻辑是一个循环,对tcp_active_pcbs
链表中的每一个pcb
进行处理。以下是主要步骤:
-
初始化:函数首先通过
tcp_active_pcbs
获得链表的头部pcb
。 -
处理每个pcb:然后,函数进入一个
while
循环,对链表中的每一个pcb
进行处理。 -
检查并处理ACK延迟:如果
pcb
的标志有TF_ACK_DELAY
,它会立即发送ACK(通过tcp_ack_now
函数),然后将数据输出到网络(通过tcp_output
函数),最后清除TF_ACK_DELAY
和TF_ACK_NOW
标志。 -
检查并处理挂起的FIN:如果
pcb
的标志有TF_CLOSEPEND
,它会清除TF_CLOSEPEND
标志,并通过tcp_close_shutdown_fin
函数发送FIN。 -
处理之前被拒绝的数据:如果
pcb
有被之前被拒绝的数据(pcb->refused_data != NULL
),它会调用tcp_process_refused_data
函数来处理这些数据。如果在处理这些数据的过程中,tcp_active_pcbs
链表发生了改变(tcp_active_pcbs_changed
变为1),那么函数将重新开始循环(通过goto tcp_fasttmr_start;
实现)。
5. 结论
通过对tcp_fasttmr
函数的分析,我们可以看出lwIP如何处理TCP协议中的一些核心任务,包括发送延迟的ACK,处理挂起的FIN,以及处理之前被上层拒绝的数据。这个函数的设计充分体现了lwIP对于嵌入式系统资源紧张的考虑,通过精细化的控制和状态管理,尽可能地减少了系统资源的消耗。
参考文献
希望这篇博客对你有所帮助。如果有任何疑问或者需要进一步的讨论,欢迎在下方留言。