文章有问题 请大家去阅读 http://tengine.taobao.org/book/index.html 中的内容
欢迎大家转载,转载请注明出处 http://blog.csdn.net/yankai0219/article/details/8011042
来自yankai0219
0.序
1.正文
问题1:如何从网络设备中获得数据?专业点的话,Linux网络协议栈中数据包的处理过程
问题2:应用层如何从传输层获得数据
解决方法:
首先:阅读以下几篇文章。
再次:自己做出一个总结。我的总结如下:
1.套接字缓冲区skb
2.数据的拷贝
3.详细讲述两次数据拷贝的过程
2.依旧存在问题
|
0.序
刚看到这个问题“Nginx如何获得数据包”时,我一下子就不知所措,根本就不知道如何获取,之前就知道socket、bind、listen就建立连接,获取数据了。
本次序言,主要讲述了我是如何思考,如何找到解决问题的切入点,以供大家参考。有些不正确的地方,请指正。
Nginx作为应用层程序,如何获得来自网络的数据呢?
这部分内容,对于一个Linux网络编程的菜鸟来讲,实在难以理解,刚接触这个问题时,无从下手。
思路1来源:http://java-mzd.iteye.com/blog/1007577 提到的“怎么理解协议与程序”
如同我们自定义的应用层协议一样:
协议只是给出了一组规范,规定我们应该怎么样(按什么规则)保存数据。
在计算机间传输的永远都是二进制字节码(对于传输层,可以理解为传输的始终是下层的IP数据包),是计算机中的程序通过对这些字节码进行逻辑分析、判断,来控制程序完成差错控制等功能。
至于解析这些字节码的程序,则可以有不同的实现,只要我们按照规则来解析,并作出相应的控制,我们大可以自己写个程序是实现相应功能。
|
即:协议就是一组规范,规定了如何保存数据。到底如何去做,那协议就不知道了。
那么到底如何去做呢?那就要交给程序来做。程序就是根据协议这一规定来编写的实际执行的代码。
那接下来就是关于程序。
对于程序来讲,我们经常会定义一些数据结构来保存数据。如果从这一角度思考的话,对于Nginx这一应用层程序来讲,其获得传输层的数据也必定是通过某一个特定的数据结构来获得。
思路2来源:从TCP/IP的四层结构考虑
众所周知,TCP/IP有四层结构(也有人说5层):数据链路层---网络层---传输层----应用层。Nginx作为应用层程序,那么它只需要从传输层获得数据。可传输层又如何获得数据呢?
举例来说,在网络设备中传输的数据帧,当我请求www.baidu.com时,百度的服务器是如何从网络设备中获得我的数据的呢?肯定是从数据链路层--网络层--传输层---应用层逐层获得数据。
这儿能够找到一个点,就是数据链路层如何从网络设备中获得数据呢?以此为出发点,去网上搜索文章,果然,找到了整个问题“应用层程序如何获得数据包”的切入点。
1.正文
问题1:如何从网络设备中获得数据?专业点的话,Linux网络协议栈中数据包的处理过程
问题2:应用层如何从传输层获得数据
解决方法:
首先:阅读以下几篇文章。
问题1需要阅读文章1
: Linux网络协议栈之数据包处理过程
文章2: 深度探索套接字缓冲区 sk_buff skb
文章3: 深度探索套接字缓冲区
这些文章都有些重复内容,建议仔细阅读文章1.
问题2需要阅读以下文章 Linux内核--网络栈实现分析(六)--应用层获取数据包(上)。
再次:自己做出一个总结。我的总结如下:
1.套接字缓冲区skb
packet:通过网卡收发的报文,包括链路层、网络层、传输层的协议头和携带的数据。
Data buffer:存储packet的内存空间。
struct sk_buff结构体是linux TCP/IP网络栈中,用于管理Data buffer的结构。
套接字缓冲区skb是用结构体struct sk_buff表示,它用于在网络系统的各层之间传递数据,处于一个核心地位,该结构体包含了一组成员数据用于承载网络数据,同时,也定义了这些数据上操作的一些函数。
通俗的来讲,从以太网帧中传上来的数据都会被解析保存到struct sk_buff结构体中,该结构体中包含了所有的数据,它用于在数据链路层、网络层、传输层中传递数据,即数据链路层、网络层、传输层所获得数据都是从struct sk_buff结构体中获得。
2.数据的拷贝
为了提高网络处理的性能,应尽量减少数据包的拷贝,目前linux协议在接收数据的时候,仅仅需要拷贝两次:
1)数据包进入网卡驱动后拷贝一次
2)从内核空间递交给用户空间的应用时再拷贝一次
3.详细讲述两次数据拷贝的过程
1)数据包进入网卡驱动后拷贝一次。
由于我刚刚接触,所以不能够从源码上给出解释,只能从大致的函数调用上给出解释,以后有机会再进行补充。
当以太网帧到达网卡时,网卡驱动程序会分配一个struct sk_buffer的结构体skb,包含以太网帧所有数据信息,
这儿有一次数据复制。会将数据包缓存结构struct sk_buff挂载到接收队列sk->receive_queue的队尾
2)从内核空间递交给用户空间的应用时再拷贝一次
总结,在一系列的调用中,会通过skb_copy_datagram数据进入结构体struct msghdr中。
这儿会将数据拷贝到用户空间。具体的函数调用参考文章《Linux内核--网络栈实现分析(六)--应用层获取数据包(上)》。
2.依旧存在问题
截止到2012年9月23日,对于Nginx如何获取数据包依旧存在以下问题
问题:虽然知道了应用程序获取数据包的大致流程(以太网帧----struct sk_buff -----struct msghdr),但是Nginx是否采用如此方式,以及如何使用数据都是未知。