Linux网络设备驱动架構學習(二)

接下來會從以下幾個方面介紹網絡設備驅動的編寫流程:

1、網絡設備的註冊與註銷

2、網絡設備的初始化

3、網絡設備的打開與釋放

4、網絡數據發送流程

5、網絡數據接收流程

6、網絡連接狀態

7、網絡參數設置和統計數據

瞭解了這幾部份內容,網絡設備驅動的編寫方法也就基本明白了

網絡設備的註冊與註銷

网络设备驱动的注册与注销使用成对出现的register_netdev()和unregister_netdev()函数完成,这两个函数的原型为:

int register_netdev(struct net_device *dev);

void unregister_netdev(struct net_device *dev);

这两个函数都接收一个 net_device 结构体指针为参数,可见 net_device 数据结构在网络设备驱动中的核心地位。

net_device 的生成和成员的赋值并非一定要由工程师逐个亲自动手完成,可以利用下面的函数帮助我们填充:
struct net_device *alloc_netdev(int sizeof_priv, const char *name, void(*setup) (struct net_device*));

struct net_device *alloc_etherdev(int sizeof_priv);

alloc_netdev()函数生成一个 net_device 结构体,对其成员赋值并返回该结构体的指针。第一个参数为设备私有成员的大小,第二个参数为设备名,第三个参数为net_device 的 setup()函数指针。setup()函数接收的参数也为 struct net_device 指针,用
于预置 net_device 成员的值。

alloc_etherdev()是 alloc_netdev()针对以太网的“快捷”函数。

完成与 alloc_enetdev()和 alloc_etherdev()函数相反功能,即释放 net_device 结构体的函数为:

void free_netdev(struct net_device *dev);

net_device 结构体的分配和网络设备驱动注册需在网络设备驱动程序的模块加载函数中进行,而 net_device 结构体的释放和网络设备驱动的注销则需在模块卸载函数中完成,如代码清单所示。

1   int xxx_init_module(void)
2 {
3 ...
4 /* 分配 net_device 结构体并对其成员赋值 */
5 xxx_dev = alloc_netdev(sizeof(struct xxx_priv), "sn%d", xxx_init);
6 if (xxx_dev == NULL)
7 ... /* 分配 net_device 失败 */
8
9 /* 注册 net_device 结构体 */
10 if ((result = register_netdev(xxx_dev)))
11 ...
12 }
13
14 void xxx_cleanup(void)
15 {
16 ...
17 /* 注销 net_device 结构体 */
18 unregister_netdev(xxx_dev);
19 /* 释放 net_device 结构体 */
20 free_netdev(xxx_dev);
21 }

網絡設備的初始化

网络设备的初始化主要需要完成如下几个方面的工作。

1、进行硬件上的准备工作,检查网络设备是否存在,如果存在,则检测设备所使用的硬件资源。

2、进行软件接口上的准备工作,分配 net_device 结构体并对其数据和函数指针成员赋值。

3、获得设备的私有信息指针并初始化其各成员的值。如果私有信息中包括自旋锁或信号量等并发或同步机制,则需对其进行初始化。

对 net_device 结构体成员及私有数据的赋值都可能需要与硬件初始化工作协同进行,即硬件检测出了相应的资源,需要根据检测结果填充 net_device 结构体成员和私有数据。 一个网络设备驱动初始化函数的模板如代码清单所示,具体的设备驱动初始化函数并不一定完全和本模板一样,但是其本质过程是一致的。

1   void xxx_init(struct net_device *dev)
2 {
3 /*设备的私有信息结构体*/
4 struct xxx_priv *priv;
5
6 /* 检查设备是否存在和设备所使用的硬件资源 */
7 xxx_hw_init();
8
9 /* 初始化以太网设备的公用成员 */
10 ether_setup(dev);
11
12 /*设置设备的成员函数指针*/
13 dev->open = xxx_open;
14 dev->stop = xxx_release;
15 dev->set_config = xxx_config;
16 dev->hard_start_xmit = xxx_tx;
17 dev->do_ioctl = xxx_ioctl;
18 dev->get_stats = xxx_stats;
19 dev->change_mtu = xxx_change_mtu;
20 dev->rebuild_header = xxx_rebuild_header;
21 dev->hard_header = xxx_header;
22 dev->tx_timeout = xxx_tx_timeout;
23 dev->watchdog_timeo = timeout;
24
25 /*如果使用 NAPI,设置 pool 函数*/
26 if (use_napi)
27 {
28 dev->poll = xxx_poll;
29 }
30
31 /* 取得私有信息,并初始化它*/
32 priv = netdev_priv(dev);
33 ... /* 初始化设备私有数据区 */
34 }

上述代码第 7 行的 xxx_hw_init()函数完成硬件相关的初始化操作,如下所示。

1、探测 xxx 网络设备是否存在。探测的方法类似于数学上的“反证法”,即先假设存在设备 xxx,访问该设备,如果设备的表现与预期的一致,就确定设备存在;否则,假设错误,设备 xxx 不存在。

2、探测设备的具体硬件配置。一些设备驱动编写得非常通用,对于同类的设备使用统一的驱动,我们需要在初始化时探测设备的具体型号。另外,即便是同一设备,在硬件上的配置也可能不一样,我们也可以探测设备所使用的硬件资源。

3、申请设备所需要的硬件资源,如用 request_region()函数进行 I/O 端口的申请等,但是这个过程可以放在设备的打开函数 xxx_open()中完成。

針對Mini2440 DM9000 驱动probe方法做一個分析就可以對上面兩個過程有一個更清晰的認識

請移步:Mini2440 DM9000 驱动分析(三)

網絡設備的打開與釋放

网络设备的打开函数需要完成如下工作。

1、使能设备使用的硬件资源,申请 I/O 区域、中断和 DMA 通道等。

2、调用 Linux 内核提供的 netif_start_queue()函数,激活设备发送队列。

网络设备的关闭函数需要完成如下工作。

1、调用 Linux 内核提供的 netif_stop_queue()函数,停止设备传输包。

2、释放设备所使用的 I/O 区域、中断和 DMA 资源。

Linux 内核提供的 netif_start_queue()和 netif_stop_queue()两个函数的原型为:

void netif_start_queue(struct net_device *dev);

void netif_stop_queue (struct net_device *dev);

根据以上分析,可得出如代码清单所示的网络设备打开和释放函数的模板。

1   int xxx_open(struct net_device *dev)
2 {
3 /* 申请端口、IRQ 等,类似于 fops->open */
4 ret = request_irq(dev->irq, &xxx_interrupt, 0, dev->name, dev);
5 ...
6 netif_start_queue(dev);
7 ...
8 }
9
10 int xxx_release(struct net_device *dev)
11 {
12 /* 释放端口、IRQ 等,类似于 fops->close */
13 free_irq(dev->irq, dev);
14 ...
15 netif_stop_queue(dev); /* can't transmit any more */
16 ...
17 }

針對Mini2440 DM9000 驱动open,stop方法做一個分析就可以對上面兩個過程有一個更清晰的認識

請移步:Mini2440 DM9000 驱动分析(四)

Linux网络设备驱动架構學習(二)的更多相关文章

  1. Linux网络设备驱动架構學習(三)

    Linux网络设备驱动架構學習(三) 接下來會從以下幾個方面介紹網絡設備驅動的編寫流程: 1.網絡設備的註冊與註銷 2.網絡設備的初始化 3.網絡設備的打開與釋放 4.網絡數據發送流程 5.網絡數據接 ...

  2. linux设备驱动归纳总结(十二):简单的数码相框【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-116926.html linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxx ...

  3. linux网络设备驱动

    Linux网络设备驱动 Linux网络驱动程序的体系结构可划分为4个层次.Linux内核源代码中提供了网络设备接口及以网络子系统的上层的代码,移植特定网络硬件的驱动程序的主要工作就是完成设备驱动功能层 ...

  4. 【Linux开发】linux设备驱动归纳总结(十二):简单的数码相框

    linux设备驱动归纳总结(十二):简单的数码相框 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  5. linux 网络设备驱动

    linux 网络驱动 谨以此文纪念过往的岁月 一.前言在linux中网络驱动也是一个大头,如何去理解网络驱动是作为一个linux驱动工程师必备的技能.不过同样的设备,在不同人的手中会有不同的效果,其原 ...

  6. Linux网络设备驱动(一) _驱动模型

    Linux素来以其强大的网络功能著名,同时, 网络设备也作为三大设备之一, 成为Linux驱动学习中必不可少的设备类型, 此外, 由于历史原因, Linux并没有强制对网络设备贯彻其"一切皆 ...

  7. Linux网络设备驱动架构

    Linux网络设备驱动程序体系结构分为四层:网络协议接口层.网络设备接口层.提供实际功能的设备驱动层以及网络设备与媒介层. (1)网络协议接口层向网络层协议提供统一的数据包收发接口,不论上层协议是AR ...

  8. Linux网络设备驱动 _驱动模型

    Linux素来以其强大的网络功能著名,同时, 网络设备也作为三大设备之一, 成为Linux驱动学习中必不可少的设备类型, 此外, 由于历史原因, Linux并没有强制对网络设备贯彻其"一切皆 ...

  9. Linux 网络设备驱动开发(一) —— linux内核网络分层结构

    Preface Linux内核对网络驱动程序使用统一的接口,并且对于网络设备采用面向对象的思想设计. Linux内核采用分层结构处理网络数据包.分层结构与网络协议的结构匹配,既能简化数据包处理流程,又 ...

随机推荐

  1. Python内置模块与标准库

    Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...

  2. 如何使用gifsicle压缩gif图片

    最近我写了一些关于如何将各种形式的多媒体格式相互转换的文章,特别是GIF动图方面的,比如如何将小视频转换成GIF动图或将GIF动图转换成视频,有很多像ImageMagick,ffmpeg这样的工具帮助 ...

  3. JS脚本病毒调试脚本-Trojan[Downloader]:JS/Nemucod

    1.前言 遇到Trojan[Downloader]:JS/Nemucod需要分析,这款病毒主要为js运行.从网上各种找js调试方法.发现52的帖子还挺沾边的. TrojanDownloader:JS/ ...

  4. 如何提升mysql replication的性能&多线程传输二进制日志

    1,最好使用内网或者专线链路传输binlog数据 (千兆网卡.还不够的话,bounding 技术,扩展带宽) 在my.cnf中强制使用内网ip传输数据bind-address=ip2,将二进制保存在独 ...

  5. tomcat报错catalina.sh: line 401: /usr/java/jdk1.7.52/bin/java: No such file or directory

    将生产服务器的Tomcat目录打包过来后解压后,启动Tomcat后,发现如下问题: # ./shutdown.sh  Using CATALINA_BASE:   /usr/local/tomcat  ...

  6. java8新特性详解(转)

    原文链接. 前言: Java 8 已经发布很久了,很多报道表明Java 8 是一次重大的版本升级.在Java Code Geeks上已经有很多介绍Java 8新特性的文章,例如Playing with ...

  7. pixel像素基础

    地址:http://www.imooc.com/video/9564 dp(安卓),pt(iphone)是物理像素 ppi是由物理像素确定的 一英寸内有多少个像素渲染,ppi越高,图片越清晰 1px ...

  8. Java 基本语法---Java运算符

    Java 基本语法---Java运算符 0. 概述 Java中的运算符主要分为以下几种: 算术运算符 赋值运算符 关系运算符 逻辑运算符 条件运算符 位运算符 其他运算符 1. 算术运算符 操作符 描 ...

  9. LeetCode(23):合并K个排序链表

    Hard! 题目描述: 合并 k 个排序链表,返回合并后的排序链表.请分析和描述算法的复杂度. 示例: 输入: [   1->4->5,   1->3->4,   2-> ...

  10. CF1064B 【Equations of Mathematical Magic】

    题目要求解$a-(a\oplus x)-x=0$的解$x$的个数 移项得$a-x=a\oplus x$ $a$的二进制形式,应该是一个$01$串,异或的过程是不能影响到两个不同的位的,所以我们按位考虑 ...