`
Michaelmatrix
  • 浏览: 207846 次
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Linux网络设备驱动指南(2)

 
阅读更多

网络数据包的接收代码说明:

首先网络接口设备插槽的接受缓冲区sk_buff必须先获得一定的内存空间,而且处在缓冲区上层的程序代码可以通过中断操作和sk_buff进行数 据交换。网包一般用中断机制来处理,也可以使用polling机制,但后者多用在分析内核计时器的时候。网络接口设备多数是用中断来处理的,这样可以提供 吞吐量和计算性能。

在snull网络模型中,模拟出的网络数据到达内存时,对应的位置指针将提交给负责接收数据的函数snull_rx来进行处理,snull_rx函 数就知道了接收到的数据长度以及在内存中的具体位置了,然后snull_rx再将数据提交到网络代码的上一层应用代码进行处理。snull_rx代码和网 包数据指针的获取代码是相互独立的。

中断机制的操作柄

绝大多数硬件是通过产生中断的事件来取得和处理器的交互的,当网络硬件接口发生新的数据收发将会产生中断事件信号给处理器以获得用于处理的计算资 源。注意但面对同样的中断事件时,异步的网络包传送和PLIP,PPP三种形式的底层中断代码实现是不一样的,在常见的中断例行程序代码可以找到区别。

snull模型的中断代码如下:

注意要锁住设备,数据收发工作完成后要释放缓冲占用的内存空间,这两项工作可以用

spin_lock(&priv->lock);

dev_kfree_skb(priv->skb);来完成。

操作器先获得准确的net_device结构指针,该指针来自于dev_id的参数。包接受工作无需调用中断操作,只要执行snull_rx动作函数就可以了。

改变联结状态的代码部分。真实网络中的传输介质上附着载波信号。拔掉网线载波信号消失,说明网络状态为关。

网络设备默认具备载波信号存在,驱动程序可通过动作函数来显式地改变状态。比如:
void netif_carrier_on (struct net_device *dev);如果驱动程序没有侦测到设备上的载波信号,那么将执行

netif_carrier_off(struct net_device *dev);动作,并告诉内核,一旦侦测到载波信号,那么将执行

void netif_carrier_on动作函数,也可用int netif_carrier_ok(struct net_device *dev);。

介质访问控制(MAC)地址的解析

介质访问控制(MAC)地址的解析简介:网络接口一般具有唯一的硬件标识号,用MAC地址来表示,如何将MAC地址和IP地址建立关联呢?下面将分别对ARP(地址解析协议),没有ARP的以太网包头的PLIP协议以及非以太网包头分别介绍。

在以太网上使用ARP,幸运的是ARP协议由内核来进行管理,网络接口不要做这些特殊的管理工作,只要接口打开时dev->addr和dev ->addr_len变量被正确地赋值,驱动程序就无需去为IP地址如何解析到MAC硬件地址而担心了,ether_setup动作为dev- >hard_header和dev->rebuild_header变量提供正确的设备方法,内核在缓冲管理详细的MAC地址管理的时候,调 用接口驱动程序来帮助建立网络数据包,内核利用ARP查询的结果并调用驱动程序中的hard_header方法释放出网络包,网络代码员一般不必须关心这 些细节。

不使用arp而直接操作硬件网包头部分的代码,修改dev->hard_header方法,snull模型就是这样:
int snull_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned int len)
{
struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
eth->h_proto = htons(type);
memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len);
eth->h_dest[ETH_ALEN-1] ^= 0x01; return(dev->hard_header_len);
}

以上功能将内核提供的信息格式化成标准的以太网包头,同时还在目标以太网地址中设定一个位,如果包头中的pkt_type被设置成 PACKET_OTHERHOST,除非接口被设置成混杂模式(promiscuous),否则这些包将被接收主机的netif_rx动作函数丢弃, plip驱动程序将硬件地址的开始的八进制设置为0xfc,而snull模型驱动设置为0x00,plip和snull模型地址效果跟以太网的点对点 (ppp)连接。

接着介绍非以太网包头,具体信息可去内核源代码库中找,绝大多数驱动程序代码员只要直接采用以太网方案实现就可以了,包中的协议如何表示的呢?比如 IP协议可以用ETH_P_IP来表示。用16位的二进制序列来表示协议。点对点连接来说,地址信息可以省略掉,因为目的地址和源地址已固定,只要提交协 议就可以了。

字符指针变量skb->mac.raw被网络层的地址解析机制使用,在网络层中实现,具体可以参考net/ipv4/arp.c源码文件。网 络设备的类型值在Linux/if_arp.h中定义,eth_type_trans函数负责为接受到的包进行以太网包头处理,例如:
skb->mac.raw = skb->data;
skb_pull(skb, dev->hard_header_len);
网络硬件设备的具体类型说明可参考drivers/net/appletalk/cops.c,drivers/net/irda/smc_ircc.c,drivers/net/ppp_generic.c等源文件。

多播网包

多播网包,就是同时发往多个网络设备的网络数据包,网包是否属于多播察看目标地址的前面几位就可以了,很多网卡硬件地址都有清楚的相应标志位,内核负责给网包付给正确的目的地址,驱动程序负责为内核控制的网络地址提供相应的数据网包就可以了,

注意: 有些网络接口可能无法处理多播网包。

内核支持多播网包时,需要设备操作方法函数、数据结构、设备标志等的支持,比如:
void (*dev->set_multicast_list) (struct net_device *dev);
struct dev_mc_list *dev->mc_list;(<-与设备相关的多播网包列表)
int dev->mc_count;
IFF_MULTICAST,
IFF_ALLMULTI(多播网包路由开启时有效),
IFF_PROMISC等,
dev_mc_list结构的定义如下:
struct dev_mc_list
{
struct dev_mc_list *next;
__u8 dmi_addr[MAX_ADDR_LEN];
unsigned char dmi_addrlen;
int dmi_users; int dmi_gusers;
};
用一段伪代码来描述,代码中以ff_开头的都是存放硬件操作的,具体代码:
void set_multicast_list(struct net_device *dev)
{
struct dev_mc_list *mcptr;
if (dev->flags & IFF_PROMISC) {ff_get_all_packets();
return;
}
/*如果包很多则用另外软件空间来排序和处理*/
if (dev->flags & IFF_ALLMULTI || dev->mc_count > FF_TABLE_SIZE){ff_get_all_multicast_packets();
return;
}
if (dev->mc_count == 0){ff_get_only_own_packets();
return;
/*所有多播地址存放在硬件过滤器中*/
}
ff_clear_mc_list();
for (mc_ptr = dev->mc_list;
mc_ptr;
mc_ptr = mc_ptr->next)
ff_store_mc_address(mc_ptr->dmi_addr);
ff_get_packets_in_multicast_list();
}
如 果接口无法处理多播包,则上述代码可简化,FF_TABLE_SIZE就是0,只需要代码的最后4个分句就可以了,但 set_multicast_list方法还是要的,需要它来通知dev->flags标志位的改变。简化后的多播包处理代码叫 nonefeatured(nf),如下:
void nf_set_multicast_list(struct net_device *dev)
{
if (dev->flags & IFF_PROMISC) nf_get_all_packets();
else nf_get_only_own_packets();
}
对于点对点的连接来说,无需设置set_multicast_list因为接口会接受到所有来的包,代码中的IFF_PROMISC变量很重要,使用tcpdump等网络包分析工具时必须开启该变量。

其他提醒说明

本文参考Linux内核版本是2.3.43,各Linux版本之间的网络子系统变量和函数的修订区别,这里省略。内核中的网络驱动部分可以看到一些可选其他方式的处理代码:

#if_def HAVE_DEVLIST
struct netdev_entry netcard_drv = {cardname, netcard_probel, NETCARD_IO_EXTENT, netcard_portlist};

#else 正常的探测例行程序代码。
了解更多其它类型的Linux设备驱动,可以参考.

分享到:
评论

相关推荐

    嵌入式设计及linux驱动开发指南——基于ARM9处理器.pdf

    第8章 网络设备驱动程序开发 8.1 网络设备驱动程序简介 8.1.1 device数据结构 8.1.2 sk_buff数据结构 8.1.3 内核的驱动程序接口 8.2 以太网控制器CS8900A 8.2.1 特性 8.2.2 工作原理 8.2.3 电路连接 8.2.4 ...

    Android驱动开发权威指南

    13.1 Linux网络设备驱动体系结构 13.2 Linux网络设备驱动结构 13.3 Linux网络设备驱动I/O实现 13.3.1网络设备初始化 13.3.2网络数据包的收发 第三篇 实践出真知——Android驱动实践篇 第14章Android HAL层的设计 ...

    嵌入式设计及linux驱动开发指南——基于ARM.

    嵌入式设计及linux驱动开发指南-基于ARM9处理器; 第一章:嵌入式系统基础;...第八章:网络设备驱动程序开发;第九章:USB驱动程序开发;第十章:图形用户接口;第十一章:系统设计开发; (文档大小:20M左右)

    Linux驱动程序的编写

    里面是几个文档: Linux内核模块和驱动的编写.doc Linux对端口资源的管理.doc Linux系统的硬件驱动程序编写原理.doc Linux设备驱动编程之内存与IO操作.doc ... 设计Linux系统网络设备驱动程序.doc

    LINUX网站建设技术指南

    第2章 服务器平台安装和设备管理 2.1 硬件选择 2.1.1 CPU、RAM和主板与性能的关系 2.1.2 硬盘的选择 2.1.3 显示卡与监视器的选择 2.1.4 电源与UPS的选择 2.2 Linux的安装准备 2.2.1 Linux的获取 2.2.2 了解你的...

    Linux内核编程指南第3版.pdf

    内容简介 《Linux内核编程指南(第3版)》面向...全书共分10章,内容分别涉及Linux内核简介、内存管理、进程间通信、Linux文件系统、设备驱动程序、网络实现方式、模块和调试,以及多重处理等Linux内核原理和开发技术。

    深入理解LINUX网络内幕(英文版).chm

    《深入理解Linux网络内幕》不仅描述了Linux网络的全貌,而且是理解Linux网络细节的有效指南。 作者Christian Benvenuti是一个专注于操作系统网络的设计者。他在书中不仅解释了Linux代码如何工作,还阐述了主要...

    Linux环境数据库管理员指南

    1.2 Linux核心 2 1.2.1 Linux的开发特点 2 1.2.2 Linux分发包 3 1.2.3 为什么要为商业Linux 版本付费 3 1.3 Linux与其他操作系统之间的差异 3 1.3.1 功能丰富 3 1.3.2 多任务 4 1.4 为什么选择 Linux 6 1.4.1 何时...

    GNU_linux编程指南

    最后,介绍了Bash编程和设备驱动编程。 本书包含大量实用实例,读者可以通过实例代码深入理解编程思想和技巧。本书另一优点是讲述了其他编程书籍通常没有提及的RPM包管理工具、文档编写以及发布许可证选择等内容,这...

    GNU_Linux编程指南.pdf

    最后,介绍了Bash编程和设备驱动编程。 本书包含大量实用实例,读者可以通过实例代码深入理解编程思想和技巧。本书的另一优点是讲述了其他编程书籍通常没有提及的RPM包管理工具、文档编写以及发布许可证选择等内容

    Linux高级编程(无加密版)

    第14章 设备驱动程序 第15章 文件系统 第16章 网络系统 第17章 系统内核机制 第四篇 Linux系统高级编程 第18章 Linux内核模块编程 第19章 有关进程通信的编程 第20章 高级线程编程 第21章 Linux系统网络编程 第22章...

    Linux中文手册

    26.Linux下的设备驱动 27.Intel740 for X 28.技术讲座:Linux自由软件的奇葩 29.网络配置问题 30.外设配置FAQ 31.Linux核心源码介绍 32.Bash 33.如何在Linux上建立DNS服务器 34.Linux下新手装网卡指南 35....

    GNU/Linux编程指南(第二版)中文版含光盘

    电子书是中文扫描版,清晰度还可以; 目录: 第1部分 Linux编程工具包 第1章 Linux及Linux编程综述 ...第31章 设备驱动程序 第7部分 补充内容 第32章 软件包管理第33章 建档 第34章 许可证的发放

    嵌入式linux内核学习资料

    Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布, 它主要受到Minix和Unix思想的启发,是一个基于...&lt;&lt;LINUX设备驱动程序(第3版).pdf&gt;&gt;

    linux内核编程指南第3版

    Linux操作系统简介 编译内核 内核入门 内存管理 进程间的通信 Linux文件系统 Linux下的设备驱动程序 网络实现方式 模块和调试 多重处理

    如何编写Qemu后端块设备驱动 - Neil1

    如何编写Qemu后端块设备驱动 - Neil1

    GNU_Linux编程指南

    最后,介绍了Bash编程和设备驱动编程。  本书包含大量实用实例,读者可以通过实例代码深入理解编程思想和技巧。本书另一优点是讲述了其他编程书籍通常没有提及的RPM包管理工具、文档编写以及发布许可证选择等内容,...

    Linux编程从入门到精通.rar

    第6章 中断处理与设备驱动程序 第7章 文件系统 第8章 网络 第9章 内核机制与模块 第10章 处理器 第12章 Linux数据结构 ———————————————————————— 第二部分 Linux内核模块编程指南 第1章 ...

Global site tag (gtag.js) - Google Analytics