[转]linux内核网络分层结构
Preface
Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计。
Linux内核采用分层结构处理网络数据包。分层结构与网络协议的结构匹配,既能简化数据包处理流程,又便于扩展和维护。
内核网络结构
在Linux内核中,对网络部分按照网络协议层、网络设备层、设备驱动功能层和网络媒介层的分层体系设计。
网络驱动功能层主要通过网络驱动程序实现。
在Linux内核,所有的网络设备都被抽象为一个接口处理,该接口提供了所有的网络操作。
net_device结构表示网络设备在内核中的情况,也就是网络设备接口。网络设备接口既包括软件虚拟的网络设备接口,如环路设备,也包括了网络硬件设备,如以太网卡。
Linux内核有一个dev_base的全局指针,指向一个设备链表,包括了系统内的所有网络设备。该设备链表每个节点是一个网络设备。
在net_device结构中提供了许多供系统访问和协议层调用的设备方法,包括初始化、打开关闭设备、数据包发送和接收等。
与网络有关的数据结构
内核对网络数据包的处理都是基于sk_buff结构的,该结构是内核网络部分最重要的数据结构。
网络协议栈中各层协议都可以通过对该结构的操作实现本层协议数据的添加或者删除。使用sk_buff结构避免了网络协议栈各层来回复制数据导致的效率低下。

sk_buff结构可以分为两个部分,一部分是存储数据包缓存,在图中表示为PackertData,另一部分是由一组用于内核管理的指针组成。
sk_buff管理的指针最主要的是下面4个:
head指向数据缓冲(PackertData)的内核首地址;
data指向当前数据包的首地址;
tail指向当前数据包的尾地址;
end 指向数据缓冲的内核尾地址。
数据包的大小在内核网络协议栈的处理过程中会发生改变,因此data和tail指针也会不断变化,而head和tail指针是不会发生改变的。
对于一个TCP数据包为例,sk_buff还提供了几个指针直接指向各层协议头。mac指针指向数据的mac头;nh指针指向网络协议头,一般是IP协议头;h指向传输层协议头,在本例中是TCP协议头。
对各层设置指针的是方便了协议栈对数据包的处理。
net_device结构
Linux内核中网络设备最重要的数据结构就是net_device结构了,它是网络驱动程序最重要的部分。
net_device结构保存在include/linux/netdevices.h头文件,理解该结构对理解网络设备驱动有很大帮助。
内核中所有网络设备的信息和操作都在net_device设备中,无论是注册网络设备,还是设置网络设备参数,都用到该结构。
下面是主要数据成员。
设备名称
总线参数
协议参数
链接层变量
接口标志
数据包接收流程
在Linux内核中,一个网络数据包从网卡接收到用户空间需要经过链路层、传输层和socket的处理,最终到达用户空间。

以DM9000网卡为例,当网卡收到数据包以后,调用中断处理函数 dm9000_interrupt(),该函数检查中断处理类型,如果是接收数据包中断,则调用 dm9000_rx()函数接收数据包到内核空间。
dm9000_rx()函数收到数据包完成后,内核会继续调用 netif_rx()函数,函数的作用是把网卡接收到数据提交给协议栈处理。
协议栈使用 net_rx_action()函数处理接收数据包队列,该函数处理数据包后如果是 IP数据包则提交给ip_recv()函数处理。ip_recv()函数主要是检查一个数据包IP头的合法性,检查通过后交给 ip_local_deliver()和 ip_local_deliver_finish()函数处理,之所以分开处理是因为内核中有防火墙相关的代码需要动态加载到此处。
IP头处理完毕后,以UDP数据包为例将交由 udp_recv()函数处理,与 ip_recv()函数类亿,该函数检查 UDP头的合法性,然后交给 udp_queue_recv()函数处理,最后提交给 sock_queue_recv()函数处理。
数据包进入 socket部分的第一个函数是 skb_recv_datagram(),该函数从内核的 socket队列取出数据包,交给 socket部分的 udp_recvmsg()函数,该函数负责处理UDP的数据,sock_recvmsg()处理提交给 sock_read()函数。
sock_read()函数读取接收到的数据缓冲,把数据返回给 sys_read()系统调用。sys_read()函数调用最终把数据复制到用户空间,供用户使得。
数据包发送流程
以UDP数据包发送流程为例,在DM9000网卡上如何发送一个数据包。

当用户空间的应用程序通过 socket函数 sento()发送一个UDP数据后,会调用内核空间的 sock_writev()函数,然后通过 sock_sendmsg()函数处理。sock_sendmsg()函数调用 inet_sendmsg()函数处理,inet_sendmsg()函数会把要发送的数据交给传输层的 udp_sendmsg()函数处理。
udp_sendmsg()函数在数据前加入UDP头,然后把数据交给 ip_build_xmit()函数处理,该函数根据 socket提供的目的 IP和端口信息构造IP头,然后调用 output_maybe_reroute()函数处理。out_maybe_reroute()函数检查数据包是否需要经过路由,最后交给 ip_output()函数写入到发送队列,写入完成后由 ip_finish_output()函数处理后续工作。
链路层的 dev_queue_xmit()函数处理发送队列,调用 DM9000网卡的发送数据包函数 dm9000_xmit()发送数据包,发送完毕后,调用 dm9000_xmit_done函数处理发送结果。
本文转自http://infohacker.blog.51cto.com/6751239/1221140
[转]linux内核网络分层结构的更多相关文章
- 【驱动】网卡驱动·linux内核网络分层结构
Preface Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程 ...
- Linux 网络设备驱动开发(一) —— linux内核网络分层结构
Preface Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程,又 ...
- Linux内核--网络栈实现分析(十一)--驱动程序层(下)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7555870 更多请查看专栏,地 ...
- Linux内核--网络栈实现分析(七)--数据包的传递过程(下)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地 ...
- Linux内核--网络栈实现分析(三)--驱动程序层+链路层(上)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7497260 更多请看专栏,地址 ...
- Linux内核--网络栈实现分析(一)--网络栈初始化
本文分析基于内核Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7488828 更多请看专栏, ...
- Linux内核--网络栈实现分析(二)--数据包的传递过程--转
转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上 ...
- Linux内核--网络栈实现分析(一)--网络栈初始化--转
转载地址 http://blog.csdn.net/yming0221/article/details/7488828 作者:闫明 本文分析基于内核Linux Kernel 1.2.13 以后的系列博 ...
- Linux内核网络数据包处理流程
Linux内核网络数据包处理流程 from kernel-4.9: 0. Linux内核网络数据包处理流程 - 网络硬件 网卡工作在物理层和数据链路层,主要由PHY/MAC芯片.Tx/Rx FIFO. ...
随机推荐
- navicat for mysql中添加注释
mysql; # 这注释持续到行尾 mysql; -- 这注释持续到行尾 mysql ; mysql+ /* 这是 多行注释 */
- 2012年及之后的ImageNet比赛的冠军、亚军和季军ImageNet winners after 2012
2012 0.15 - Supervision (AlexNet) - ~ 60954656 params 0.26 - ISI (ensemble of features) 0.27 - LEAR ...
- cocos2d js ScrollView的使用方法
游戏中非常多须要用到ScrollView的情况,也就是须要滚动一片区域. 这里有两种实现方法,一种是使用cocos studio的方式,另外一种是手写代码.先看第一种 第一种记得在设置滚动区域时选取裁 ...
- Furure的简单介绍和使用
引子:
- SoundPool 音频播放 API 详解【示例】
demo地址:https://github.com/baiqiantao/PermissionTest.git 一个大坑:SoundPool最多只能播放时长10s左右.大小70kb左右(这些值是我多次 ...
- 总结div里面水平垂直居中的实现方法
最近经常碰到要垂直居中的问题,所以想着总结一下:关于如何设置小盒子在大盒子里面水平垂直方向同时居中的实现方法有很多种,下面仅列举了常用的几种. 首先看一下要实现的效果图及对应的html代码: < ...
- idea启动崩溃问题
idea启动崩溃问题 内存已经给到1024m了: 注意到项目比较大,有个参数ReservedCodeCasheSize,把这个修改为1024m, 学习了:https://www.cnblogs.com ...
- Cognos配置oracle类型内容库时报错
Cognos初次安装,创建内容库为Oracle数据库类型的时候,报下面的错误 [Content Manager database connection][ ERROR ] The database c ...
- 微博推荐算法学习(Weibo Recommend Algolrithm)
原文:http://hijiangtao.github.io/2014/10/06/WeiboRecommendAlgorithm/ 基础及关联算法 作用:为微博推荐挖掘必要的基础资源.解决推荐时的通 ...
- MFC apps must not include windows.h
用VS2008建立一个DLL项目,一开始的时候不想用MFC, 所以选择的是使用标准Windows库. 使用了一段时间后又想用MFC了,所以把选项改成使用在共享 DLL 中使用 MFC. 但是编译的时候 ...