TCP可靠传输及流量控制系列一:FREEBSD中TCP定时器的基石

FREEBSDTCP定时器的基石

TCP连接中的七个定时器:连接建立定时器、重传定时器、延迟ACK定时器、持续定时器、保活定时器、FIN_WAIT_2定时器、TIME_WAIT定时器都是由两个定时器函数来实现的,一个函数没200ms调用一次(快速定时器);另一个函数每500ms调用一次(慢速定时器)。

1、tcp_fasttimo函数

void

tcp_fasttimo()

{

register struct inpcb *inp;

register struct tcpcb *tp;

int s = splnet();

inp = tcb.inp_next;

if (inp)

for (; inp != &tcb; inp = inp->inp_next)

if ((tp = (struct tcpcb *)inp->inp_ppcb) &&

    (tp->t_flags & TF_DELACK)) {

tp->t_flags &= ~TF_DELACK;

tp->t_flags |= TF_ACKNOW;

tcpstat.tcps_delack++;

(void) tcp_output(tp);

}

splx(s);

}

tcp_fasttimo函数每隔200ms被pr_fasttimo调用一次,用于操作延迟ACK定时器。

该函数检查TCP链表中每个具有对应TCP控制块的Internet PCB,如果TF_DELACK标志置位,清除该标志,并置TF_ACKNOW标志。调用tcp_output,由于TF_ACKNOW标置已置位,ACK被发送。

     void

     pffasttimo(arg)

     void *arg;

     {

     register struct domain *dp;

     register struct protosw *pr;

     for (dp = domains; dp; dp = dp->dom_next)

     for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)

     if (pr->pr_fasttimo)

     (*pr->pr_fasttimo)();

     timeout(pffasttimo, NULL, hz/5);

     }

该函数用两个for循环对内核支持的所有域的每个定义有pr_slowtimo函数的协议调用pr_slowtimo函数。该函数没通过timeout(pfslowtimo, (void *)0, hz/2)500ms调用自己一次。

domaininit()

{

register struct domain *dp;

register struct protosw *pr;

#undef unix

#ifndef lint

ADDDOMAIN(unix);

ADDDOMAIN(route);

#ifdef INET

ADDDOMAIN(inet);

#endif

#ifdef NS

ADDDOMAIN(ns);

#endif

#ifdef ISO

ADDDOMAIN(iso);

#endif

#ifdef CCITT

ADDDOMAIN(ccitt);

#endif

#include "imp.h"

#if NIMP > 0

ADDDOMAIN(imp);

#endif

#endif

for (dp = domains; dp; dp = dp->dom_next) {

if (dp->dom_init)

(*dp->dom_init)();

for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)

if (pr->pr_init)

(*pr->pr_init)();

}

if (max_linkhdr < 16) /* XXX */

max_linkhdr = 16;

max_hdr = max_linkhdr + max_protohdr;

max_datalen = MHLEN - max_hdr;

timeout(pffasttimo, (void *)0, 1);

timeout(pfslowtimo, (void *)0, 1);

}

只看最后两行(标志为蓝色的两行),在系统初始化期间,内核调用domaininit来链接结构domain和protorsw,并调用timeout函数启动pffasttimopfslowtimo

2、tcp_slowtimo

void

tcp_slowtimo()

{

register struct inpcb *ip, *ipnxt;

register struct tcpcb *tp;

int s = splnet();

register int i;

tcp_maxidle = TCPTV_KEEPCNT * tcp_keepintvl;

/*

 * Search through tcb's and update active timers.

 */

ip = tcb.inp_next;

if (ip == 0) {

splx(s);

return;

}

for (; ip != &tcb; ip = ipnxt) {

ipnxt = ip->inp_next;

tp = intotcpcb(ip);

if (tp == 0)

continue;

for (i = 0; i < TCPT_NTIMERS; i++) {

if (tp->t_timer[i] && --tp->t_timer[i] == 0) {

(void) tcp_usrreq(tp->t_inpcb->inp_socket,

    PRU_SLOWTIMO, (struct mbuf *)0,

    (struct mbuf *)i, (struct mbuf *)0);

if (ipnxt->inp_prev != ip)

goto tpgone;

}

}

tp->t_idle++;

if (tp->t_rtt)

tp->t_rtt++;

tpgone:

;

}

tcp_iss += TCP_ISSINCR/PR_SLOWHZ; /* increment iss */

#ifdef TCP_COMPAT_42

if ((int)tcp_iss < 0)

tcp_iss = 0; /* XXX */

#endif

tcp_now++; /* for timestamps */

splx(s);

}

tcp_slowtimo函数,每隔500ms pr_slowtimo调用一次。它操作其他6个定时器:连接建立定时器、重传定时器、持续定时器、保活定时器、FIN_WAIT_2定时器和2MSL定时器

两个for循环检测连接控制块中的每个具有对应TCP控制块的Internet PCB,测试每个连接的所有定时器,如果非0,计数器减1。如果减为0,则发送PRU_SLOWTIMO请求。

           void

           pfslowtimo(arg)

           void *arg;

           {

            register struct domain *dp;

            register struct protosw *pr;

            for (dp = domains; dp; dp = dp->dom_next)

            for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)

            if (pr->pr_slowtimo)

           (*pr->pr_slowtimo)();

            timeout(pfslowtimo, NULL, hz/2);

           }

该函数用两个for循环对内核支持的所有域的每个定义有pr_slowtimo函数的协议调用pr_slowtimo函数。该函数没通过timeout(pfslowtimo, (void *)0, hz/2)500ms调用自己一次。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值