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. 以后的博客将更新到自己的域名pythonsite.com,欢迎访问

    以后的博客将更新到自己的域名pythonsite.com,欢迎访问

  2. .Net Core连接RabbitMQ集群

    var connectionFactory = new ConnectionFactory() { //HostName = "192.168.205.128", 集群不在此处声明 ...

  3. 【Pyhon】获取文件MIME类型,根据文件类型自定义文件后缀

    场景 下载样本,都是MD5命名的无后缀文件,需要自己手动查询然后修改文件后缀. 根据文件类型自定义后缀可以很方便地根据后缀判断用什么工具分析. 使用说明 libmagic 地址:https://pyp ...

  4. 通过 EXPLAIN 分析低效 SQL 的执行计划

    每个列的简单解释如下:  select_type:表示 SELECT 的类型,常见的取值有 SIMPLE(简单表,即不使用表连接 或者子查询).PRIMARY(主查询,即外层的查询).UNION(U ...

  5. ASP.NET中Request.ApplicationPath、Request.FilePath、Request.Path、.Request.MapPath、

    1.Request.ApplicationPath->当前应用的目录    Jsp中, ApplicationPath指的是当前的application(应用程序)的目录,ASP.NET中也是这 ...

  6. 再谈CentOS 7程序自启动

    上次发现了/etc/init.d下已经没有启动脚本了,然后对于启动乱序自己在rc.local中重排. 其实想一想这些应用的自启动终归还是需要通过脚本来执行的. 一.脚本在哪里? /usr/lib/sy ...

  7. 查找网内活跃IP和自动传输文本

    ifconfig p32p1|egrep -o "broadcast [^ ]*" |grep -o "[0-9.]*"grep -o "broadc ...

  8. APP性能测试开始之旅

    你是不是也跟我一样在工作中存在着同样的问题,APP版本在上线后不断的会有市场人员或者用户反馈页面加载慢,进入页面loading很久(实际我们设置的加载超时是15秒,15秒内加载出内容则显示,15秒外未 ...

  9. 关于idtcpserver的使用

    原文:http://blog.csdn.net/hnxxcxg/article/details/2798019 用idTCPServer,客户端接上来时,如何取得客户端的IP? IP:=AThread ...

  10. Linux命令执行顺序— ||和&&和; 比较

    Linux命令执行顺序— ||和&&和; command1 && command2: &&左边的command1执行成功(返回0表示成功)后,& ...