扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
一.前言
Linux的源码里,网络接口的实现部份是非常值得一读的,通过读源码,不仅对网络协议有更深的了解,也有助于在网络编程的时候,对应用函数有更精确的了解和把握。
本文把重点放在网络接口程序的总体结构上,希望能作为读源码时一些指导性的文字。
本文以Linux2.4.16内核作为讲解的对象,内核源码可以在www.kernel.org上下载。我读源码时参考的是[lxr.linux.no]这个交差参考的网站,我个人认为是一个很好的工具,如果有条件最好上这个网站。
二.网络接口程序的结构
Linux的网络接口分为四部份:网络设备接口部份,网络接口核心部份,网络协议族部份,以及网络接口socket层。
网络设备接口部份主要负责从物理介质接收和发送数据。实现的文件在linu/driver/net目录下面。网络接口核心部份是整个网络接口的关键部位,它为网络协议提供统一的发送接口,屏蔽各种各样的物理介质,同时又负责把来自下层的包向合适的协议配送。它是网络接口的中枢部份。它的主要实现文件在linux/net/core目录下,其中linux/net/core/dev.c为主要管理文件。
网络协议族部份是各种具体协议实现的部份。Linux支持TCP/IP,IPX,X.25,AppleTalk等的协议,各种具体协议实现的源码在linux/net/目录下相应的名称。在这里主要讨论TCP/IP(IPv4)协议,实现的源码在linux/net/ipv4,其中linux/net/ipv4/af_inet.c是主要的管理文件。
网络接口Socket层为用户提供的网络服务的编程接口。主要的源码在linux/net/socket.c。
三.网络设备接口部份
物理层上有许多不同类型的网络接口设备, 在文件include/linux/if_arp.h的28行里定义了ARP能处理的各种物理设备的标志符。网络设备接口要负责具体物理介质的控制,从物理介质接收以及发送数据,并对物理介质进行诸如最大数据包之类的各种设置。这里我们以比较简单的3Com3c501以太网卡的驱动程序为例,大概讲一下这层的工作原理。源码在Linux/drivers/net/3c501.c。
我们从直觉上来考虑,一个网卡当然最主要的是完成数据的接收和发送,在这里我们来看看接收和发送的过程是怎么样的。
发送相对来说比较简单,在Linux/drivers/net/3c501.c的475行开始的el_start_xmit()这个函数就是实际向3Com3c501以太网卡发送数据的函数,具体的发送工作不外乎是对一些寄存器的读写,源码的注释很清楚,大家可以看看。
接收的工作相对来说比较复杂。通常来说,一个新的包到了,或者一个包发送完成了,都会产生一个中断。在Linux/drivers/net/3c501.c中的572行,开始的el_interrupt()函数里面,前半部份处理的是发送完包以后的汇报,后半部份处理的是一个新来的包,就是说接收到了新的数据。el_interrupt()函数并没有对新的包进行太多的处理,就交给了接收处理函数el_receive()。el_receive()首先检查接收的包是否正确,如果是一个“好”包就会为包分配一个缓冲结构(dev_alloc_skb()),这样驱动程序对包的接收工作就完成了,通过调用上层的函数netif_rx()(net/core/dev.c1214行) ,把包交给上层。
现在驱动程序有了发送和接收数据的功能了,驱动程序怎么样和上层建立联系呢?就是说接收到包以后怎么送给上层,以及上层怎么能调用驱动程序的发送函数呢?
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者