一、应用层

前端之家收集整理的这篇文章主要介绍了一、应用层前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转载地址

作者:闫明

本文分析基于Linux Kernel 1.2.13

注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析、”(下)“表示分析是从上向下分析。

 上篇:

上一篇博文中我们从宏观上分析了Linux内核中网络栈的初始化过程,这里我们再从宏观上分析一下一个数据包在各网络层的传递的过程。

我们知道网络的OSI模型和TCP/IP模型层次结构如下:

上文中我们看到了网络栈的层次结构:

我们就从最底层开始追溯一个数据包的传递流程。

1、网络接口层

* 硬件监听物理介质,进行数据的接收,当接收的数据填满了缓冲区,硬件就会产生中断,中断产生后,系统会转向中断服务子程序。

* 在中断服务子程序中,数据会从硬件的缓冲区复制到内核的空间缓冲区,并包装成一个数据结构(sk_buff),然后调用对驱动层的接口函数netif_rx()将数据包发送给链路层。该函数的实现在net/inet/dev.c中,(在整个网络栈实现中dev.c文件的作用重大,它衔接了其下的驱动层和其上的网络层,可以称它为链路层模块的实现)

该函数的实现如下:

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="
http://blog.csdn.net/geekcome/article/details/7492423"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;copy

 
     
  1.  
  2.  
  3.  
  4.  
  5.  
  6.   
  7.   
  8.  netif_rx( sk_buff *skb)  
  9. {  
  10.       dropping = 0;  
  11.   
  12.      
  13.  
  14.  
  15.  
  16.   
  17.     skb->sk = NULL;  
  18.     skb->free = 1;  
  19.     (skb->stamp.tv_sec==0)  
  20.         skb->stamp = xtime;  
  21.   
  22.      
  23.  
  24.   
  25.   
  26.      (!backlog_size)  
  27.         dropping = 0;  
  28.       (backlog_size > 300)  
  29.         dropping = 1;  
  30.   
  31.      (dropping)   
  32.     {  
  33.         kfree_skb(skb, FREE_READ);  
  34.         ;  
  35.     }  
  36.   
  37.      
  38.  
  39.   
  40.   
  41.     IS_SKB(skb);  
  42.   
  43.     skb_queue_tail(&backlog,skb);  
  44.     backlog_size++;  
  45.     
  46.      
  47.  
  48.  
  49.   
  50.   
  51.     mark_bh(NET_BH);  
  52.     ;  
  53. }  

该函数中用到了bootom half技术,该技术的原理是将中断处理程序人为的分为两部分,上半部分是实时性要求较高的任务,后半部分可以稍后完成,这样就可以节省中断程序的处理时间。可整体的提高系统的性能。该技术将会在后续的博文中详细分析。

我们从上一篇分析中知道,在网络栈初始化的时候,已经将NET的下半部分执行函数定义成了net_bh(在socket.c文件中1375行左右)

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;copy

 
    bh_base[NET_BH].routine= net_bh;  

* 函数net_bh的实现在net/inet/dev.c中

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;copy

 
     
  1.  
  2.  
  3.  
  4.  
  5.  
  6.   
  7.    
  8.  net_bh( *tmp)  
  9. {  
  10.      sk_buff *skb;  
  11.      packet_type *ptype;  
  12.      packet_type *pt_prev;  
  13.     unsigned  type;  
  14.   
  15.      
  16.  
  17.   
  18.   
  19.      (set_bit(1, (*)&in_bh))  
  20.         ;  
  21.   
  22.      
  23.  
  24.  
  25.  
  26.   
  27.   
  28.     dev_transmit();  
  29.     
  30.      
  31.  
  32.  
  33.  
  34.   
  35.   
  36.     cli();  
  37.       
  38.      
  39.  
  40.   
  41.        
  42.     ((skb=skb_dequeue(&backlog))!=NULL)  
  43.     {  
  44.          
  45.  
  46.   
  47.         backlog_size--;  
  48.   
  49.         sti();  
  50.           
  51.             
  52.  
  53.  
  54.  
  55.  
  56.   
  57.   
  58.         skb->h.raw = skb->data + skb->dev->hard_header_len;  
  59.         skb->len -= skb->dev->hard_header_len;  
  60.   
  61.             
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.   
  71.           
  72.         type = skb->dev->type_trans(skb, skb->dev);  
  73.   
  74.          
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.   
  85.         pt_prev = NULL;  
  86.          (ptype = ptype_base; ptype != NULL; ptype = ptype->next)   
  87.         {  
  88.               
  89.              ((ptype->type == type || ptype->type == htons(ETH_P_ALL)) && (!ptype->dev || ptype->dev==skb->dev))  
  90.             {  
  91.                  
  92.  
  93.  
  94.   
  95.                 (pt_prev)  
  96.                 {  
  97.                      sk_buff *skb2;  
  98.   
  99.                     skb2=skb_clone(skb, GFP_ATOMIC);  
  100.   
  101.                      
  102.  
  103.  
  104.   
  105.   
  106.                     (skb2)  
  107.                         pt_prev->func(skb2, skb->dev, pt_prev);  
  108.                                               
  109.                                               
  110.                 }  
  111.                   
  112.                 pt_prev=ptype;  
  113.             }  
  114.         }   
  115.           
  116.          
  117.  
  118.   
  119.   
  120.         (pt_prev)  
  121.             pt_prev->func(skb, pt_prev);  
  122.          
  123.  
  124.   
  125.        
  126.           
  127.             kfree_skb(skb, FREE_WRITE);  
  128.   
  129.          
  130.  
  131.  
  132.  
  133.   
  134.   
  135.         dev_transmit();  
  136.         cli();  
  137.     }     
  138.       
  139.      
  140.  
  141.   
  142.        
  143.     in_bh = 0;  
  144.     sti();  
  145.       
  146.      
  147.  
  148.   
  149.        
  150.     dev_transmit();  
  151. }  

2、网络层* 就以IP数据包为例来说明,那么从链路层向网络层传递时将调用ip_rcv函数。该函数完成本层的处理后会根据IP首部中使用的传输层协议来调用相应协议的处理函数。

UDP对应udp_rcv、TCP对应tcp_rcv、ICMP对应icmp_rcv、IGMP对应igmp_rcv(虽然这里的ICMP,IGMP一般成为网络层协议,但是实际上他们都封装在IP协议里面,作为传输层对待)

这个函数比较复杂,后续会详细分析。这里粘贴一下,让我们对整体了解更清楚

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;copy

 
     
  1.  
  2.   
  3.   
  4.  ip_rcv( sk_buff *skb,  device *dev,  packet_type *pt)  
  5. {  
  6.      iphdr *iph = skb->h.iph;  
  7.      sock *raw_sk=NULL;  
  8.     unsigned  hash;  
  9.     unsigned  flag = 0;  
  10.     unsigned  opts_p = 0;     
  11.      inet_protocol *ipprot;  
  12.       options opt;  
  13.   
  14.      brd=IS_MYADDR;  
  15.      is_frag=0;  
  16.   
  17.      err;  
  18.   
  19.   
  20.     ip_statistics.IpInReceives++;  
  21.   
  22.      
  23.  
  24.   
  25.   
  26.     skb->ip_hdr = iph;  
  27.   
  28.      
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.   
  36.   
  37.      (skb->len<( iphdr) || iph->ihl<5 || iph->version != 4 ||  
  38.         skb->lentot_len) || ip_fast_csum((unsigned  *)iph, iph->ihl) !=0)  
  39.     {  
  40.         ip_statistics.IpInHdrErrors++;  
  41.         kfree_skb(skb, FREE_WRITE);  
  42.         (0);  
  43.     }  
  44.       
  45.      
  46.  
  47.   
  48.   
  49.   
  50.       
  51.      ((err=ip_fw_chk(iph,dev,ip_fw_blk_chain,ip_fw_blk_policy, 0))!=1)  
  52.     {  
  53.         (err==-1)  
  54.             icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);  
  55.         kfree_skb(skb, FREE_WRITE);  
  56.          0;     
  57.     }  
  58.   
  59.   
  60.       
  61.      
  62.  
  63.  
  64.   
  65.   
  66.     skb->len=ntohs(iph->tot_len);  
  67.   
  68.      
  69.  
  70.  
  71.   
  72.   
  73.      (iph->ihl != 5)  
  74.     {     
  75.         memset(( *) &opt, (opt));  
  76.          (do_options(iph, &opt) != 0)  
  77.              0;  
  78.         opts_p = 1;  
  79.     }  
  80.   
  81.      
  82.  
  83.   
  84.        
  85.     (iph->frag_off)  
  86.     {  
  87.          (iph->frag_off & 0x0020)  
  88.             is_frag|=1;  
  89.          
  90.  
  91.   
  92.       
  93.          (ntohs(iph->frag_off) & 0x1fff)  
  94.             is_frag|=2;  
  95.     }  
  96.       
  97.      
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.   
  108.   
  109.      ( iph->daddr != skb->dev->pa_addr && (brd = ip_chk_addr(iph->daddr)) == 0)  
  110.     {  
  111.          
  112.  
  113.   
  114.   
  115.         (skb->pkt_type!=PACKET_HOST || brd==IS_BROADCAST)  
  116.         {  
  117.             kfree_skb(skb,FREE_WRITE);  
  118.              0;  
  119.         }  
  120.   
  121.          
  122.  
  123.   
  124.   
  125.   
  126.         ip_forward(skb, dev, is_frag);  
  127.   
  128.  
  129. saddr,iph->daddr);*/  
  130.         ip_statistics.IpInAddrErrors++;  
  131.   
  132.          
  133.  
  134.  
  135.   
  136.   
  137.         kfree_skb(skb, FREE_WRITE);  
  138.         (0);  
  139.     }  
  140.       
  141.   
  142.   
  143.     (brd==IS_MULTICAST && iph->daddr!=IGMP_ALL_HOSTS && !(dev->flags&IFF_LOOPBACK))  
  144.     {  
  145.          
  146.  
  147.   
  148.          ip_mc_list *ip_mc=dev->ip_mc_list;  
  149.           
  150.         {  
  151.             (ip_mc==NULL)  
  152.             {     
  153.                 kfree_skb(skb, FREE_WRITE);  
  154.                  0;  
  155.             }  
  156.             (ip_mc->multiaddr==iph->daddr)  
  157.                 ;  
  158.             ip_mc=ip_mc->next;  
  159.         }  
  160.         (1);  
  161.     }  
  162.   
  163.      
  164.  
  165.   
  166.        
  167.   
  168.     ip_acct_cnt(iph, ip_acct_chain);  
  169.   
  170.   
  171.      
  172.  
  173.   
  174.   
  175.     (is_frag)  
  176.     {  
  177.           
  178.         skb=ip_defrag(iph,skb,dev);  
  179.         (skb==NULL)  
  180.              0;  
  181.         skb->dev = dev;  
  182.         iph=skb->h.iph;  
  183.     }  
  184.       
  185.            
  186.   
  187.      
  188.  
  189.   
  190.   
  191.     skb->ip_hdr = iph;  
  192.     skb->h.raw += iph->ihl*4;  
  193.       
  194.      
  195.  
  196.   
  197.        
  198.     hash = iph->protocol & (SOCK_ARRAY_SIZE-1);  
  199.       
  200.       
  201.     ((raw_sk=raw_prot.sock_array[hash])!=NULL)  
  202.     {  
  203.          sock *sknext=NULL;  
  204.          sk_buff *skb1;  
  205.         raw_sk=get_sock_raw(raw_sk, hash,  iph->saddr, iph->daddr);  
  206.         (raw_sk)    
  207.         {  
  208.               
  209.             {  
  210.                   
  211.                 sknext=get_sock_raw(raw_sk->next, iph->saddr, iph->daddr);  
  212.                 (sknext)  
  213.                     skb1=skb_clone(skb, GFP_ATOMIC);  
  214.                   
  215.                     ;    
  216.                 (skb1)  
  217.                     raw_rcv(raw_sk, skb1,iph->daddr);  
  218.                 raw_sk=sknext;  
  219.             }  
  220.             (raw_sk!=NULL);  
  221.               
  222.               
  223.         }  
  224.     }  
  225.       
  226.      
  227. h.raw now points at the protocol beyond the IP header. 
  228.   
  229.   
  230.     hash = iph->protocol & (MAX_INET_PROTOS -1);  
  231.      (ipprot = ( inet_protocol *)inet_protos[hash];ipprot != NULL;ipprot=( inet_protocol *)ipprot->next)  
  232.     {  
  233.          sk_buff *skb2;  
  234.   
  235.          (ipprot->protocol != iph->protocol)  
  236.             ;  
  237.         
  238.  
  239.  
  240.  
  241.  
  242.   
  243.          (ipprot->copy || raw_sk)  
  244.         {  
  245.             skb2 = skb_clone(skb, GFP_ATOMIC);  
  246.             (skb2==NULL)  
  247.                 ;  
  248.         }  
  249.           
  250.         {  
  251.             skb2 = skb;  
  252.         }  
  253.         flag = 1;  
  254.   
  255.             
  256.  
  257.  
  258.  
  259.   
  260.         ipprot->handler(skb2, opts_p ? &opt : 0, iph->daddr,  
  261.                 (ntohs(iph->tot_len) - (iph->ihl * 4)),  
  262.                 iph->saddr, ipprot);  
  263.   
  264.     }  
  265.   
  266.      
  267.  
  268.  
  269.  
  270.  
  271.   
  272.   
  273.     (raw_sk!=NULL)      
  274.         raw_rcv(raw_sk, skb, iph->daddr);  
  275.       (!flag)       
  276.     {  
  277.          (brd != IS_BROADCAST && brd!=IS_MULTICAST)  
  278.             icmp_send(skb, ICMP_PROT_UNREACH, FREE_WRITE);  
  279.     }  
  280.   
  281.     (0);  
  282. }  

3、传输层

如果在IP数据报的首部标明的是使用TCP传输数据,则在上述函数中会调用tcp_rcv函数。该函数的大体处理流程为:

“所有使用TCP 协议的套接字对应sock 结构都被挂入tcp_prot 全局变量表示的proto 结构之sock_array 数组中,采用以本地端口号为索引的插入方式,所以当tcp_rcv 函数接收到一个数据包,在完成必要的检查和处理后,其将以TCP 协议首部中目的端口号(对于一个接收的数据包而言,其目的端口号就是本地所使用的端口号)为索引,在tcp_prot 对应sock 结构之sock_array 数组中得到正确的sock 结构队列,在辅之以其他条件遍历该队列进行对应sock 结构的查询,在得到匹配的sock 结构后,将数据包挂入该sock 结构中的缓存队列中(由sock 结构中receive_queue 字段指向),从而完成数据包的最终接收。”

该函数的实现也会比较复杂,这是由TCP协议的复杂功能决定的。附代码如下:

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7492423"&gt;copy

 
     
  1.  
  2.   
  3.    
  4.  tcp_rcv( sk_buff *skb,  options *opt,  
  5.     unsigned  daddr, unsigned  len,  
  6.     unsigned  saddr,  redo,  inet_protocol * protocol)  
  7. {  
  8.      tcphdr *th;  
  9.      sock *sk;  
  10.      syn_ok=0;  
  11.       
  12.      (!skb)   
  13.     {  
  14.         printk();  
  15.         (0);  
  16.     }  
  17.   
  18.      (!dev)   
  19.     {  
  20.         printk();  
  21.         (0);  
  22.     }  
  23.     
  24.     tcp_statistics.TcpInSegs++;  
  25.     
  26.     (skb->pkt_type!=PACKET_HOST)  
  27.     {  
  28.         kfree_skb(skb,FREE_READ);  
  29.         (0);  
  30.     }  
  31.     
  32.     th = skb->h.th;  
  33.   
  34.      
  35.  
  36.   
  37.   
  38.     sk = get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);  
  39.   
  40.      
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.   
  48.        
  49.      (sk!=NULL && (sk->zapped || sk->state==TCP_CLOSE))  
  50.         sk=NULL;  
  51.   
  52.      (!redo)   
  53.     {  
  54.          (tcp_check(th, len, daddr ))   
  55.         {  
  56.             skb->sk = NULL;  
  57.             kfree_skb(skb,FREE_READ);  
  58.              
  59.  
  60.  
  61.   
  62.             (0);  
  63.         }  
  64.         th->seq = ntohl(th->seq);  
  65.   
  66.           
  67.          (sk == NULL)   
  68.         {  
  69.              
  70. rst is 0 send a reset (checked in tcp_reset) 
  71.   
  72.             tcp_reset(daddr, th, &tcp_prot, opt,skb->ip_hdr->tos,255);  
  73.             skb->sk = NULL;  
  74.              
  75.  
  76.   
  77.             kfree_skb(skb, FREE_READ);  
  78.             (0);  
  79.         }  
  80.   
  81.         skb->len = len;  
  82.         skb->acked = 0;  
  83.         skb->used = 0;  
  84.         skb->free = 0;  
  85.         skb->saddr = daddr;  
  86.         skb->daddr = saddr;  
  87.       
  88.           
  89.         cli();  
  90.          (sk->inuse)   
  91.         {  
  92.             skb_queue_tail(&sk->back_log, skb);  
  93.             sti();  
  94.             (0);  
  95.         }  
  96.         sk->inuse = 1;  
  97.         sti();  
  98.     }  
  99.       
  100.     {  
  101.          (sk==NULL)   
  102.         {  
  103.             tcp_reset(daddr,255);  
  104.             skb->sk = NULL;  
  105.             kfree_skb(skb, FREE_READ);  
  106.             (0);  
  107.         }  
  108.     }  
  109.   
  110.   
  111.      (!sk->prot)   
  112.     {  
  113.         printk();  
  114.         (0);  
  115.     }  
  116.   
  117.   
  118.      
  119.  
  120.   
  121.        
  122.      (sk->rmem_alloc + skb->mem_len >= sk->rcvbuf)   
  123.     {  
  124.         kfree_skb(skb, FREE_READ);  
  125.         release_sock(sk);  
  126.         (0);  
  127.     }  
  128.   
  129.     skb->sk=sk;  
  130.     sk->rmem_alloc += skb->mem_len;  
  131.   
  132.      
  133.  
  134.  
  135.  
  136.  
  137.   
  138.   
  139.     (sk->state!=TCP_ESTABLISHED)         
  140.     {  
  141.       
  142.          
  143.  
  144.   
  145.        
  146.         (sk->state==TCP_LISTEN)  
  147.         {  
  148.             (th->ack)    
  149.                 tcp_reset(daddr,saddr,th,sk->prot,opt,sk->ip_tos, sk->ip_ttl);  
  150.   
  151.              
  152.  
  153.  
  154.  
  155.  
  156.   
  157.                  
  158.             (th->rst || !th->syn || th->ack || ip_chk_addr(daddr)!=IS_MYADDR)  
  159.             {  
  160.                 kfree_skb(skb, FREE_READ);  
  161.                 release_sock(sk);  
  162.                  0;  
  163.             }  
  164.           
  165.              
  166.  
  167.   
  168.           
  169.             tcp_conn_request(sk, daddr, tcp_init_seq());  
  170.           
  171.              
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.   
  179.                
  180.             release_sock(sk);  
  181.              0;  
  182.         }  
  183.       
  184.           
  185.          (sk->state == TCP_SYN_RECV && th->syn && th->seq+1 == sk->acked_seq)  
  186.         {  
  187.             kfree_skb(skb, FREE_READ);  
  188.             release_sock(sk);  
  189.              0;  
  190.         }  
  191.           
  192.          
  193.  
  194.  
  195.   
  196.          
  197.         (sk->state==TCP_SYN_SENT)  
  198.         {  
  199.               
  200.             (th->ack)  
  201.             {  
  202.                   
  203.                 (!tcp_ack(sk,len))  
  204.                 {  
  205.                      
  206. rst is checked in tcp_reset()] */  
  207.                     tcp_statistics.TcpAttemptFails++;  
  208.                     tcp_reset(daddr,  
  209.                         sk->prot,sk->ip_ttl);  
  210.                     kfree_skb(skb, FREE_READ);  
  211.                     release_sock(sk);  
  212.                     (0);  
  213.                 }  
  214.                 (th->rst)  
  215.                      tcp_std_reset(sk,skb);  
  216.                 (!th->syn)  
  217.                 {  
  218.                      
  219.   
  220.                     kfree_skb(skb, FREE_READ);  
  221.                     release_sock(sk);  
  222.                      0;  
  223.                 }  
  224.                  
  225.  
  226.  
  227.   
  228.                 syn_ok=1;     
  229.                 sk->acked_seq=th->seq+1;  
  230.                 sk->fin_seq=th->seq;  
  231.                 tcp_send_ack(sk->sent_seq,sk->acked_seq,sk,sk->daddr);  
  232.                 tcp_set_state(sk, TCP_ESTABLISHED);  
  233.                 tcp_options(sk,th);  
  234.                 sk->dummy_th.dest=th->source;  
  235.                 sk->copied_seq = sk->acked_seq;  
  236.                 (!sk->dead)  
  237.                 {  
  238.                     sk->state_change(sk);  
  239.                     sock_wake_async(sk->socket, 0);  
  240.                 }  
  241.                 (sk->max_window==0)  
  242.                 {  
  243.                     sk->max_window = 32;  
  244.                     sk->mss = min(sk->max_window, sk->mtu);  
  245.                 }  
  246.             }  
  247.               
  248.             {  
  249.                   
  250.                 (th->syn && !th->rst)  
  251.                 {  
  252.                      
  253.   
  254.                     (sk->saddr==saddr && sk->daddr==daddr &&  
  255.                         sk->dummy_th.source==th->source &&  
  256.                         sk->dummy_th.dest==th->dest)  
  257.                     {  
  258.                         tcp_statistics.TcpAttemptFails++;  
  259.                          tcp_std_reset(sk,skb);  
  260.                     }  
  261.                     tcp_set_state(sk,TCP_SYN_RECV);  
  262.                       
  263.                      
  264.  
  265.  
  266.   
  267.                 }         
  268.                   
  269.                 kfree_skb(skb, FREE_READ);  
  270.                 release_sock(sk);  
  271.                  0;  
  272.             }  
  273.              
  274.  
  275.   
  276.              rfc_step6;  
  277.         }  
  278.   
  279.      
  280.  
  281.  
  282.  
  283.   
  284.       
  285.   
  286.   
  287.          (sk->state == TCP_TIME_WAIT && th->syn && sk->dead &&   
  288.             after(th->seq, sk->acked_seq) && !th->rst)  
  289.         {  
  290.              seq=sk->write_seq;  
  291.             (sk->debug)  
  292.                 printk();  
  293.             tcp_statistics.TcpEstabResets++;         
  294.             sk->rmem_alloc -= skb->mem_len;  
  295.             skb->sk = NULL;  
  296.             sk->err=ECONNRESET;  
  297.             tcp_set_state(sk, TCP_CLOSE);  
  298.             sk->shutdown = SHUTDOWN_MASK;  
  299.             release_sock(sk);  
  300.             sk=get_sock(&tcp_prot, daddr);  
  301.              (sk && sk->state==TCP_LISTEN)  
  302.             {  
  303.                 sk->inuse=1;  
  304.                 skb->sk = sk;  
  305.                 sk->rmem_alloc += skb->mem_len;  
  306.                 tcp_conn_request(sk,seq+128000);  
  307.                 release_sock(sk);  
  308.                  0;  
  309.             }  
  310.             kfree_skb(skb, FREE_READ);  
  311.              0;  
  312.         }  
  313.   
  314.     }  
  315.   
  316.      
  317.  
  318.  
  319.  
  320.   
  321.       
  322.     (!tcp_sequence(sk,len,dev))  
  323.     {  
  324.         kfree_skb(skb, FREE_READ);  
  325.         release_sock(sk);  
  326.          0;  
  327.     }  
  328.   
  329.     (th->rst)  
  330.          tcp_std_reset(sk,skb);  
  331.       
  332.      
  333.  
  334.   
  335.        
  336.     (th->syn && !syn_ok)  
  337.     {  
  338.         tcp_reset(daddr, skb->ip_hdr->tos, 255);  
  339.          tcp_std_reset(sk,skb);     
  340.     }  
  341.   
  342.      
  343.  
  344.   
  345.        
  346.   
  347.     (th->ack && !tcp_ack(sk,len))  
  348.     {  
  349.          
  350.  
  351.   
  352.            
  353.         (sk->state==TCP_SYN_RECV)  
  354.         {  
  355.             tcp_reset(daddr,sk->ip_ttl);  
  356.         }  
  357.         kfree_skb(skb, FREE_READ);  
  358.         release_sock(sk);  
  359.          0;  
  360.     }  
  361.       
  362. rfc_step6:        
  363.   
  364.      
  365.  
  366.   
  367.           
  368.     (tcp_urg(sk, len))  
  369.     {  
  370.         kfree_skb(skb, FREE_READ);  
  371.         release_sock(sk);  
  372.          0;  
  373.     }  
  374.       
  375.       
  376.      
  377.  
  378.   
  379.       
  380.     (tcp_data(skb, FREE_READ);  
  381.         release_sock(sk);  
  382.          0;  
  383.     }  
  384.   
  385.      
  386.  
  387.    
  388.       
  389.     release_sock(sk);  
  390.      0;  
  391. }  

4、应用层

当用户需要接收数据时,首先根据文件描述符inode得到socket结构和sock结构,然后从sock结构中指向的队列recieve_queue中读取数据包,将数据包COPY到用户空间缓冲区。数据就完整的从硬件中传输到用户空间。这样也完成了一次完整的从下到上的传输。

下篇:

在博文中分析了数据包从网卡设备经过驱动链路层,网络层,传输层到应用层的过程。

本文就分析一下本机产生数据是如何通过传输层,网络层到达物理层的。

综述来说,数据流程图如下:

一、应用层

应用层可以通过系统调用或文件操作来调用内核函数,BSD层的sock_write()函数会调用INET层的inet_wirte()函数。

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="
http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
     
  1.  
  2.  
  3.   
  4.   
  5.   sock_write( inode *inode,  file *file,  *ubuf,  size)  
  6. {  
  7.      socket *sock;  
  8.      err;  
  9.       
  10.      (!(sock = socki_lookup(inode)))   
  11.     {  
  12.         printk();  
  13.         (-EBADF);  
  14.     }  
  15.   
  16.      (sock->flags & SO_ACCEPTCON)   
  17.         (-EINVAL);  
  18.       
  19.     (size<0)  
  20.          -EINVAL;  
  21.     (size==0)  
  22.          0;  
  23.           
  24.      ((err=verify_area(VERIFY_READ,ubuf,size))<0)  
  25.          err;  
  26.     (sock->ops->write(sock, ubuf, size,(file->f_flags & O_NONBLOCK)));  
  27. }  

INET层会调用具体传输层协议的write函数,该函数是通过调用本层的inet_send()函数实现功能的,inet_send()函数的UDP协议对应的函数为udp_write()

<div class="dp-highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
      inet_send( socket *sock,  *ubuf,  size,  noblock,   
  1.            unsigned flags)  
  2. {  
  3.      sock *sk = ( sock *) sock->data;  
  4.      (sk->shutdown & SEND_SHUTDOWN)   
  5.     {  
  6.         send_sig(SIGPIPE, current, 1);  
  7.         (-EPIPE);  
  8.     }  
  9.     (sk->err)  
  10.          inet_error(sk);  
  11.       
  12.     (inet_autobind(sk)!=0)  
  13.         (-EAGAIN);  
  14.     (sk->prot->write(sk, (unsigned  *) ubuf, noblock, flags));  
  15. }  
  16.   
  17.   inet_write( socket *sock,  noblock)  
  18. {  
  19.      inet_send(sock,size,noblock,0);  
  20. }  

二、传输层

在传输层udp_write()函数调用本层的udp_sendto()函数完成功能

<div class="dp-Highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
     
  1.  
  2.   
  3.   
  4.   udp_write( sock *sk, unsigned  *buff,  len,  
  5.       unsigned flags)  
  6. {  
  7.     (udp_sendto(sk, buff, flags, NULL, 0));  
  8. }  

udp_send()函数完成sk_buff结构相应的设置和报头的填写后会调用udp_send()来发送数据。具体的实现过程后面会详细分析。

而在udp_send()函数中,最后会调用ip_queue_xmit()函数,将数据包下放的网络层。

下面是udp_prot定义:

<div class="dp-Highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
     proto udp_prot = {  
  1.     sock_wmalloc,  
  2.     sock_rmalloc,  
  3.     sock_wfree,  
  4.     sock_rfree,  
  5.     sock_rspace,  
  6.     sock_wspace,  
  7.     udp_close,  
  8.     udp_read,  
  9.     udp_write,  
  10.     udp_sendto,  
  11.     udp_recvfrom,  
  12.     ip_build_header,  
  13.     udp_connect,  
  14.     NULL,  
  15.     ip_queue_xmit,  
  16.     NULL,  
  17.     udp_rcv,  
  18.     datagram_select,  
  19.     udp_ioctl,  
  20.     ip_setsockopt,  
  21.     ip_getsockopt,  
  22.     128,  
  23.     0,  
  24.     {NULL,},  
  25.     ,  
  26.     0, 0  
  27. };  

<div class="dp-Highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
      udp_send( sock *sk,  sockaddr_in *sin,  
  1.      unsigned  *from,  rt)  
  2. {  
  3.      sk_buff *skb;  
  4.      device *dev;  
  5.      udphdr *uh;  
  6.     unsigned  *buff;  
  7.     unsigned  saddr;  
  8.      size, tmp;  
  9.      ttl;  
  10.     
  11.      
  12.  
  13.   
  14.        
  15.     ........................  
  16.   
  17.      
  18.  
  19.   
  20.        
  21.     ..........................  
  22.      
  23.  
  24.   
  25.        
  26.     ..............................  
  27.   
  28.      
  29.  
  30.   
  31.        
  32.     memcpy_fromfs(buff, from, len);  
  33.   
  34.      
  35.  
  36.   
  37.        
  38.     udp_send_check(uh, sin->sin_addr.s_addr, skb->len - tmp, sk);  
  39.   
  40.      
  41.  
  42.   
  43.        
  44.     udp_statistics.UdpOutDatagrams++;  
  45.        
  46.     sk->prot->queue_xmit(sk, 1);  
  47.     (len);  
  48. }  

三、网络层

 在网络层,函数ip_queue_xmit()的功能是将数据包进行一系列复杂的操作,比如是检查数据包是否需要分片,是否是多播等一系列检查,最后调用dev_queue_xmit()函数发送数据。

<div class="dp-Highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
     
  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.   
  8.   
  9.  ip_queue_xmit( sock *sk,  
  10.            sk_buff *skb,  free)  
  11. {  
  12.      iphdr *iph;  
  13.     unsigned  *ptr;  
  14.   
  15.       
  16.     ............  
  17.      
  18.  
  19.   
  20.   
  21.   
  22.     ...........  
  23.   
  24.      
  25.  
  26.  
  27.  
  28. ip_hdr to avoid this mess and the fixed 
  29.  
  30.   
  31.   
  32.     ..............  
  33.      
  34.  
  35.   
  36.   
  37.     (free!=2)  
  38.         iph->id      = htons(ip_id_count++);  
  39.       
  40.         free=1;  
  41.   
  42.       
  43.      (sk == NULL)  
  44.         free = 1;  
  45.   
  46.     skb->free = free;  
  47.   
  48.      
  49.  
  50.  
  51.  
  52.   
  53.   
  54.     ................  
  55.   
  56.      
  57.  
  58.   
  59.   
  60.     ip_send_check(iph);  
  61.   
  62.      
  63.  
  64.   
  65.   
  66.      
  67.  
  68.  
  69.   
  70.     .......................  
  71.   
  72.      
  73.  
  74.  
  75.  
  76.  
  77.   
  78.   
  79.     ......................  
  80.      
  81.  
  82.   
  83.        
  84.     ip_statistics.IpOutRequests++;  
  85.         .............................  
  86.     .............................  
  87.         ((dev->flags&IFF_BROADCAST) && iph->daddr==dev->pa_brdaddr && !(dev->flags&IFF_LOOPBACK))  
  88.         ip_loopback(dev,skb);  
  89.           
  90.      (dev->flags & IFF_UP)  
  91.     {  
  92.          
  93.  
  94.  
  95.   
  96.   
  97.          (sk != NULL)  
  98.         {  
  99.             dev_queue_xmit(skb, sk->priority);  
  100.         }  
  101.           
  102.         {  
  103.             dev_queue_xmit(skb, SOPRI_NORMAL);  
  104.         }  
  105.     }  
  106.       
  107.     {  
  108.         ip_statistics.IpOutDiscards++;  
  109.          (free)  
  110.             kfree_skb(skb, FREE_WRITE);  
  111.     }  
  112. }  

四、驱动层(链路层)

函数中,函数调用调用具体设备的发送函数来发送数据包

dev->hard_start_xmit(skb,dev);

具体设备的发送函数在网络初始化的时候已经设置了。

这里以8390网卡为例来说明驱动层的工作原理,在net/drivers/8390.c中函数ethdev_init()函数中设置如下:

<div class="dp-Highlighter bg_cpp">
<div class="bar">
<div class="tools">
[cpp] <a class="ViewSource" title="view plain" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;view plain<a class="CopyToClipboard" title="copy" href="http://blog.csdn.net/geekcome/article/details/7545855"&gt;copy

 
      
  1.  ethdev_init( device *dev)  
  2. {  
  3.      (ei_debug > 1)  
  4.         printk(version);  
  5.       
  6.      (dev->priv == NULL) {  
  7.          ei_device *ei_local;  
  8.           
  9.         dev->priv = kmalloc(( ei_device), GFP_KERNEL);  
  10.         memset(dev->priv, ( ei_device));  
  11.         ei_local = ( ei_device *)dev->priv;  
  12.   
  13.         ei_local->pingpong = 1;  
  14.   
  15.     }  
  16.       
  17.       
  18.      (dev->open == NULL)  
  19.         dev->open = &ei_open;函数  
  20.     stop entry also. */  
  21.     dev->hard_start_xmit = &ei_start_xmit;函数,定义在8390.c中  
  22.     dev->get_stats   = get_stats;  
  23.   
  24.     dev->set_multicast_list = &set_multicast_list;  
  25.   
  26.   
  27.     ether_setup(dev);  
  28.           
  29.      0;  
  30. }  

驱动中的发送函数比较复杂,和硬件关系紧密,这里不再详细分析。

这样就大体分析了下网络数据从应用层到物理层的数据通路,后面会详细分析。

猜你在找的Linux相关文章