Chinaunix首页 | 论坛 | 博客
  • 博客访问: 154502
  • 博文数量: 41
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-14 10:16
文章分类
文章存档

2011年(1)

2010年(5)

2009年(35)

我的朋友

分类: LINUX

2009-08-24 17:56:15

tcp.c文件的tcp_readable函数

978计划工作组 2009-8-24

1函数源码

/*

 *    Walk down the receive queue counting readable data until we hit the end or we find a gap

 *    in the received data queue (ie a frame missing that needs sending to us). Not

 *    sorting using two queues as data arrives makes life so much harder.

 */

 

static int tcp_readable(struct sock *sk)

{

       unsigned long counted;

       unsigned long amount;

       struct sk_buff *skb;

       int sum;

       unsigned long flags;

 

       if(sk && sk->debug)

             printk("tcp_readable: %p - ",sk);

 

       save_flags(flags);

       cli();

       if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL)

       {

              restore_flags(flags);

             if(sk && sk->debug)

                    printk("empty\n");

             return(0);

       }

 

       counted = sk->copied_seq;    /* Where we are at the moment */

       amount = 0;

 

       /*

        *    Do until a push or until we are out of data.

        */

        

       do

       {

              if (before(counted, skb->h.th->seq))   /* Found a hole so stops here */

                     break;

              sum = skb->len -(counted - skb->h.th->seq);      /* Length - header but start from where we are up to (avoid overlaps) */

              if (skb->h.th->syn)

                     sum++;

              if (sum > 0)

              {                                 /* Add it up, move on */

                     amount += sum;

                     if (skb->h.th->syn)

                            amount--;

                     counted += sum;

              }

              /*

               * Don't count urg data ... but do it in the right place!

               * Consider: "old_data (ptr is here) URG PUSH data"

               * The old code would stop at the first push because

               * it counted the urg (amount==1) and then does amount--

               * *after* the loop.  This means tcp_readable() always

               * returned zero if any URG PUSH was in the queue, even

               * though there was normal data available. If we subtract

               * the urg data right here, we even get it to work for more

               * than one URG PUSH skb without normal data.

               * This means that select() finally works now with urg data

               * in the queue.  Note that rlogin was never affected

               * because it doesn't use select(); it uses two processes

               * and a blocking read().  And the queue scan in tcp_read()

               * was correct.  Mike

               */

              if (skb->h.th->urg)

                     amount--;       /* don't count urg data */

              if (amount && skb->h.th->psh) break;

              skb = skb->next;

       }

       while(skb != (struct sk_buff *)&sk->receive_queue);

 

       restore_flags(flags);

       if(sk->debug)

             printk("got %lu bytes.\n",amount);

       return(amount);

}

2函数用途

查看目前可读数据的长度

3调用关系

4语句注释

4.1 counted = sk->copied_seq;

sk->copied_seq本地已被读取的最后一个数据的序列号加1

4.2 if (before(counted, skb->h.th->seq))   /* Found a hole so stops here */

              break;

       sum = skb->len -(counted - skb->h.th->seq);

skb->len:接收链表的某节点的数据包长度,不包括tcp头、ip头和MAC

counted用于定位下个可读取的字节的序列号,包括标志字节数

sk->h.th->seqtcp头的序列号,即本节点数据的起始序列号

beforecounted小于sk->h.th->seq则返回1,否则返回0;如为1则表示数据流出现了断裂所以执行break退出while循环,直到无断裂后继续读取。

sum:用于计算某个sk_buff节点未读取的且未统计的字节数,包括标志字节数

4.3  if (skb->h.th->syn)

              sum++;

skb->h.th->syn:同步数据标志位,占1个序列号

4.4  if (sum > 0)

       {                                  /* Add it up, move on */

              amount += sum;

              if (skb->h.th->syn)

                     amount--;

              counted += sum;

              }

amount:统计可读取的字节数,不包括标志位。

整体解释:如果sum大于零表示有数据或有标志位被置位(ack标志除外),因amount不包括标志位所以amount加了sum后还要把标志位减去,而counted包括标志位(ack标志除外)所以不用减。

4.5  if (skb->h.th->urg)

              amount--;   /* don't count urg data */

       if (amount && skb->h.th->psh) break;

skb->h.th->urg值为1表示紧急指针字段值有效,否则无效。紧急数据是将接收的数据迅速传替给应用程序的一种手段。

amount--:紧急标志被置1后,我们称数据传送进入紧急模式,实现中将紧急数据处理成一个字节,这种处理是实现相关的,即数据长度为1且占1个序列号,所以counted不能减1,而amount又不统计紧急数据,所以此处要减1,因为本身对于紧急数据的处理方式TCP规范上并无明确说明,各具体实现可以自行对如何处理紧急数据进行各自的解释。

skb->h.th->pshpsh1时的意义如同urg1表示需要将数据立刻交给应用程序,所以此处要break

阅读(1062) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~