Linux 的网络系统主要是基于 BSD UNIX
的套接字机制。

在系统与驱动程序之间定义了数据结构 sk_buff
进行传输数据。系统支持对发送数据和接收数据缓存,提供流控机制并提供对多协议的支持。

1、 linux 网络驱动程序的体系结构

linux 网络驱动程序的体系结构从上到下分为4层。各层作用例如以下:

(1)      网络协议接口层向网络层协议提供统一的数据包收发接口。不论上层是IP还是ARP。都通过
dev_queue_xmit 函数发送数据。并通过 net_rx
函数接收数据。这一层的存在使得上层协议独立于详细的设备。

(2)      网络设备接口层向协议接口层提供统一的用于描写叙述据详细网络设备属性和操作的结构体 net_dev。net_dev是设备驱动功能层中各函数的容器。

网络协议接口层从宏观上规划了详细操作硬件的设备驱动功能层的结构。

(3)      设备驱动功能层各函数是网络设备接口层 net_dev
数据结构的详细成员。是驱使网络设备硬件完毕对应动作的程序。通过 hard_start_xmit
函数启动发送操作,并通过网络设备上的中断触发接收操作。

因为网络数据包的接收由中断引发,设备驱动功能层中还有一个主体部分是中断处理函数,中断处理函数负责读取硬件上接收的数据包并传递给上层协议,可能包括了xxx_interrupt
和 xxx_rx
函数。

xxx_interrupt
函数完毕中断类型推断等基本工作, xxx_rx
函数完毕数据包的生成和递交上层等复杂工作。

(4)      网络设备与媒介层是完毕数据包发送和接收的物理实体,包含了网路适配器饿坏详细的传输媒介,网络设备被设备驱动功能层中的函数物理上驱动。在linux中。网络设备和媒介都能够是虚拟的。

在linux 中全部网络系统都抽象为一个接口。由结构体 struct net_device
来表示网络设备在内核中的执行情况,即网络设备接口。网络设备接口既包含了纯软件网络设备接口。也包含了硬件网络设备接口。全部的网络设备都是通过以 dev_base
为头指针的设备链表来管理的。该设备链表中的每个元素代表一个网络接口。结构体 net_device
中包括了非常多供系统訪问和协议层调用的设备方法,包括了 init
函数(设备初始化和系统注冊)、open
函数(打开网络设备)、stop
函数(关闭网络设备)、hard_start_xmit
函数(处理数据包发送)和中断处理函数等。

2、   网络设备的初始化

网络设备的初始化主要是 struct net_device
中的 init
函数指针所指向的初始化函数来完毕。

当内核启动或者载入网络驱动模块的时候,就会调用 init
函数。init
函数通过检測物理设备的硬件特征推断网络物理设备是不是存在。然后才决定是不是启用这个驱动程序。

接着对设备进行资源配置,配置好之后就能够向系统申请资源,如中断和 i/o
空间。最后对 net_device
对应的成员变量初始化。这样一个网络设备才干被系统使用。

对于一个新加入的设备。则须要构造设备的 net_device
数据结构,然后向linux
内核注冊设备并申请内存空间。

3、   数据包的发送和接收

当网络设备被激活的时候,调用 net_device
中的 open
函数指针。打开网络设备。并使用 net_device
中的 hard_header
函数指针来建立硬件帧头信息。

然后通过 dev_queue_xmit
协议接口层函数来调用 net_device
中的 hard_start_xmit
函数指针完毕数据包的发送。hard_start_xmit
函数负责把存放在套接字缓冲区(sk_buff)中的数据发送到物理设备。

普通情况下,设备受到数据就会产生一个中断,在中断处理时驱动程序申请一块 sk_buff
。从硬件读出数据并放到申请好的缓冲区中,然后填充sk_buff
的一些信息。最后调用 netif_rx
函数把接收到的数据包传到网络协议的上层进行处理。

当网络设备被激活的时候。调用 net_device
中的 open
函数指针,打开网络设备,并使用 net_device
中的 hard_header
函数指针来建立硬件帧头信息。然后通过 dev_queue_xmit
协议接口层函数来调用 net_device
中的 hard_start_xmit
函数指针完毕数据包的发送。hard_start_xmit
函数负责把存放在套接字缓冲区(sk_buff)中的数据发送到物理设备。

普通情况下,设备受到数据就会产生一个中断,在中断处理时驱动程序申请一块 sk_buff
,从硬件读出数据并放到申请好的缓冲区中,然后填充sk_buff
的一些信息。最后调用 netif_rx
函数把接收到的数据包传到网络协议的上层进行处理。

sk_buff 结构体(即套接字缓冲区)用于在linux 网络子系统中的各层之间传递数据。当发送数据包的时候,linux内核的网络处理模块必须建立一个包括要传输的数据包的 sk_buff
,然后将 sk_buff
递交给下层,各层在 sk_buff
中加入不同的协议头直至交给网络设备发送。当网络设备从网络媒介上接收到数据包的时候,必须将接收到的数据装换为 sk_buff
数据结构并传递给上层,各层去掉对应的协议头直至给交用户。

4、   网络设备的模块载入

网络设备驱动程序载入方式有内核载入和模块载入两种方式。

系统内核有专门载入网络设备的过程,也能够通过 module_init
宏为系统加入新网络设备。此处主要讨论网络设备的模块载入。其基本流程为:

(1)      通过 module_init
宏修饰的函数会在模块载入(或系统启动)时被调用;

(2)      网络设备被检測到后,通过调用
register_netdev 函数在 linux
系统中把设备加入到系统的网络设备链表 dev_base
的末尾;

(3)      注冊成功,将调用net_device
中的 init
函数,初始化设备。

通过 register_netdev 函数注冊网络设备是一个动态载入的过程。在 linux 2.6
内核中,全部网络设备都是用该函数载入的。模块载入不存在为网络设备预留空间,从而节省了系统内存资源。

5、 net_device
结构细节

netdevice.h文件保存在 include/linux
文件夹中

(1)      全局信息

char                   name[IFNAMSIZ];

设备名称。

分配的编号从零開始。

unsigned long          state;

设备状态。包括若干标识。

struct net_device      *next;

指向全局链表下一个设备的指针。

(2)      硬件信息

unsignedlong           mem_end;

unsigned long          mem_start;

设备内存信息。保存了设备使用的共享内存值起始和终止地址

unsigned long          base_addr;

网络接口的的I/O基地址。

unsigned int           irq;

被赋予的中断号。

unsigned char          if_port;

指定在多port设备上使用哪个port。

unsigned char          dma;

为设备分配的DMA通道。用于显示信息(ifconfig命令)。

(3)      设备方法

下面仅列举使用接口必需的方法。

int                     (*open)(struct net_device*dev);

打开接口。在ifconfig激活接口时,接口将被打开。

open函数应该注冊全部的系统资源。打开硬件并对设备运行其它所需的设置。

int                     (*stop)(struct net_device*dev);

停止接口。该函数运行的操作与open函数相反。

int                     (*hard_header) (struct sk_buff *skb,

                         structnet_device *dev,

                         unsigned short type,

                         void *daddr,

                         void *saddr,

                         unsigned len);

该函数依据先前检索到的源和目标硬件地址建立硬件头。该函数任务是将作为參数传递进入的信息,组织成设备特有的适当硬件头。

eth_header
是以太网类型接口的默认函数。ether_setup
将该成员赋值成eth_header。

 int                     (*rebuild_header)(structsk_buff *skb);

该函数用来在数据传输包之前,完毕ARP解析之后,又一次建立硬件头。

  void                    (*tx_timeout) (structnet_device *dev);

如果数据包的传输在合理的时间段内失败。则如果丢失了中断或接口被锁住。这时将调用该方法。tx_timeout
负责解决这个问题并又一次開始数据包的传输。

int                     (*set_config)(structnet_device *dev,

                                      struct ifmap *map);

改变接口配置。该函数是配置驱动程序的入口点。利用set_config
能够在执行中改变设备的I/O地址和中断号。

struct net_device_stats* (*get_stats)(struct net_device*dev);

当应用程序须要获得接口上的统计信息的时候。将会调用该函数。

Linux网络驱动程序的更多相关文章

  1. 简单linux网络驱动程序

    本文代码参考<LINUX设备驱动程序>第十七章 网络驱动程序 网络地址和虚拟主机地址为: snullnet0 192.168.0.0 snullnet1 192.168.1.0 local ...

  2. 转:Linux网卡驱动程序编写

    Linux网卡驱动程序编写 [摘自 LinuxAID] 工作需要写了我们公司一块网卡的Linux驱动程序.经历一个从无到有的过程,深感技术交流的重要.Linux作为挑战微软垄断的强有力武器,日益受到大 ...

  3. 深入理解Linux网络技术内幕——中断与网络驱动程序

    接收到帧时通知驱动程序     在网络环境中.设备(网卡)接收到一个数据帧时,须要通知驱动程序进行处理. 有一下几种通知机制: 轮询:     内核不断检查设备是否有话要说.(比較耗资源,但在一些情况 ...

  4. 《Linux Device Drivers》 第十七章 网络驱动程序——note

    基本介绍 第三类是标准的网络接口Linux设备,本章介绍的内核,其余的交互网络接口描述 网络接口,必须使用特定的内核数据结构本身注册,与外部分组交换数据线打电话时准备 经常使用的文件上的网络接口操作是 ...

  5. linux网络设备驱动程序

    4.linux网络设备驱动程序体系结构 -------------------------------------- | 数据包发送 | 数据包接收 | ----->网络协议接口层 | dev_ ...

  6. 理解 Linux 网络栈(3):QEMU/KVM + VxLAN 环境下的 Segmentation Offloading 技术(发送端)

    本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...

  7. 理解 Linux 网络栈(2):非虚拟化Linux 环境中的 Segmentation Offloading 技术

    本系列文章总结 Linux 网络栈,包括: (1)Linux 网络协议栈总结 (2)非虚拟化Linux环境中的网络分段卸载技术 GSO/TSO/UFO/LRO/GRO (3)QEMU/KVM + Vx ...

  8. Linux网络编程&内核学习

    c语言: 基础篇 1.<写给大家看的C语言书(第2版)> 原书名: Absolute Beginner's Guide to C (2nd Edition) 原出版社: Sams 作者: ...

  9. linux网络子系统内核分析

    1.选择路由 若要将数据包发至PC2,则linux系统通过查询路由表可知168.1.1.10(目的地址)的网关地址为192.168.1.1,此时linux系统选择网卡1发送数据包. 2.邻居子系统(通 ...

随机推荐

  1. css3 animate基本属性

    Css3animate属性 属性 描述 Css Animation 所有动画属性的简写属性,除了animation-play-state属性 Animation:name duration timin ...

  2. 深入理解 python 元类

    一.什么的元类 # 思考: # Python 中对象是由实例化类得来的,那么类又是怎么得到的呢? # 疑问: # python 中一切皆对象,那么类是否也是对象?如果是,那么它又是那个类实例化而来的呢 ...

  3. SwiftUI 官方教程(二)

    SwiftUI 官方教程(二) 2. 自定义 Text View 为了自定义 view 的显示,我们可以自己更改代码,或者使用 inspector 来帮助我们编写代码. 在构建 Landmarks 的 ...

  4. ROS-launch文件标签解读

    前言:ROS提供了一个同时启动节点管理器(master)和多个节点的途径,即使用启动文件(launch file).事实上,在ROS功能包中,启动文件的使用是非常普遍的.任何包含两个或两个以上节点的系 ...

  5. Css问题 margin float 文档流 背景图底部充满

    今天来整理一下做网页遇到的问题吧 1.插入背景图片并使图片居于div底部充满整个行. <style> background:url(xxx.jpg) no-repeat; backgrou ...

  6. SqlServer数据库基本用法

    . 利用T-SQL语句,创建数据库(工资管理数据库),要求如下: 数据库初始大小:3MB:文件大小按兆字节3MB自动增长,增长限制为:15MB: 数据库日志文件初始大小:1MB: 文件大小按百分比5% ...

  7. GCC G++ Make CMake自我科普

    Linux下gcc g++ make cmake 联系和区别 C/C++程序从编写到可执行一般经历这几个阶段 编写源代码 编译器编译代码生成目标文件,如.o文件 链接器链接目标文件和其他目标文件/库文 ...

  8. C++中内存分配、函数调用和返回值问题

    转载博客:http://blog.csdn.net/q_l_s/article/details/52176159(源地址找不到,就贴了这位大神的博客地址,他也是转载的,不过要是学习的话,他的博客很不错 ...

  9. java servlet 3.0文件上传

    在以前,处理文件上传是一个很痛苦的事情,大都借助于开源的上传组件,诸如commons fileupload等.现在好了,很方便,便捷到比那些组件都方便至极.以前的HTML端上传表单不用改变什么,还是一 ...

  10. 配置postgreSQL允许外部连接

    配置远 程连接PostgreSQL数据库的步骤很简单,只需要修改 %PostgreSQL_path%/data 目录下的 pg_hba.conf 和 postgresql.conf. 一.修改pg_h ...