本文主要介绍linux内核中TCP的重传定时器机制:用到的源代码是2.6.38
在一个tcp连接中,如果一方过了rto时间内都没收到对方的ACK,会触发重传并调用tcp_write_timer定时器处理函数
其中RTO表示重传时间,RTO是动态计算的,需要考虑到当前的重传次数。
tcp_write_timer调用tcp_retransmit_timer重传处理函数,后者会调用tcp_write_timeout判断重传次数是否超过最大次数(默认12次,约9分钟)
在一个tcp连接中,如果一方过了rto时间内都没收到对方的ACK,会触发重传并调用tcp_write_timer定时器处理函数
其中RTO表示重传时间,RTO是动态计算的,需要考虑到当前的重传次数。
tcp_write_timer调用tcp_retransmit_timer重传处理函数,后者会调用tcp_write_timeout判断重传次数是否超过最大次数(默认12次,约9分钟)
是的话关闭当前连接,否则重传一个skb,代码如下
static void tcp_write_timer(unsigned long data)
{
struct sock *sk = (struct sock *)data;
struct inet_connection_sock *icsk = inet_csk(sk);
int event;
bh_lock_sock(sk); //加锁,防止其他下部分任务同时执行
if (sock_owned_by_user(sk)) { //sock结构被用户进程锁住,暂时放弃并重设定时器(HZ / 20)秒后再执行:HZ是时钟中断每秒发生的次数
/* Try again later */
sk_reset_timer(sk, &icsk->icsk_retransmit_timer, jiffies + (HZ / 20));
goto out_unlock;
}
if (sk->sk_state == TCP_CLOSE || !icsk->icsk_pending) //关闭了或者定时器处理函数还没初始化
goto out;
if (time_after(icsk->icsk_timeout, jiffies)) { //还没到时间呢
sk_reset_timer(sk, &icsk->icsk_retransmit_timer, icsk->icsk_timeout);
goto out;
}
event =