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

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设备驱动程序开发指南.pdf

    《嵌入式Linux设备驱动程序开发指南》是针对嵌入式Linux系统中设备驱动程序开发的一本专业书籍,由西班牙作者Alberto Liberal de los Ríos撰写,专注于讲解如何为使用设备树的嵌入式Linux系统开发驱动。本书特别...

    linux设备驱动4.0

    3. **网络设备驱动**:网络设备驱动主要涉及网卡、无线设备等,它们负责处理网络数据包的发送和接收。网络驱动通常使用内核的网络子系统,并遵循套接字层协议。 《Linux设备驱动4.0》详细介绍了这些驱动的编写方法...

    【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.6.7z

    3. **Linux驱动程序开发**:讲解Linux驱动程序的分类,如字符设备驱动、块设备驱动、网络设备驱动等,以及它们与用户空间的交互机制,如系统调用、中断处理、设备文件等。 4. **设备树(Device Tree)**:由于I.MX6...

    Linux设备驱动程序.pdf

    - **分类**:Linux设备驱动主要分为三类:字符设备驱动、块设备驱动和网络设备驱动。字符设备通常用于处理顺序的、非缓冲的数据流;块设备用于处理随机访问的、缓冲的数据流;网络设备则负责数据在网络中的传输。 #...

    【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf

    指南中还涉及了Linux驱动实验,如Linux多点电容触摸屏实验、Linux音频驱动实验、Linux块设备驱动实验等。在进行这些实验之前,读者需要了解Linux内核驱动开发的基本概念,比如驱动模块的加载与卸载、字符设备驱动的...

    Linux设备驱动程序(中文版第三版).pdf

    接着,书中详细讨论了字符设备、块设备和网络设备驱动的实现,包括设备注册、数据传输、I/O控制等方面。对于字符设备,会介绍open、read、write等标准文件操作函数的实现;对于块设备,将涉及缓冲区管理和请求队列的...

    精通LINUX设备驱动程序开发

    本书基于Linux内核2.6版本,不仅详细讲解了Linux设备驱动程序开发的基础知识,还深入探索了诸如PCMCIA、USB、I2C、视频、音频、内存、无线通信等开发中必须面对的难点问题。除此之外,作者还分享了许多技术内幕,并...

    【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.1.pdf.7z

    接着,书中会深入讲解Linux驱动程序的结构和开发流程,包括字符设备、块设备、网络设备等各种类型驱动的编写。驱动程序的主要任务是为硬件提供操作系统级别的接口,使应用程序能够通过标准API访问硬件资源。 此外,...

    Linux设备驱动(LDD) 中文第三版.pdf

    Linux设备驱动可以分为字符设备驱动、块设备驱动和网络设备驱动等不同类型。每种类型的设备驱动有着不同的特点和应用场景。字符设备驱动通常用于键盘、鼠标等输入输出设备;块设备驱动则负责管理硬盘、SSD等存储设备...

    Linux驱动程序开发指南

    在Linux内核中,设备驱动程序通过file_operations结构暴露其入口点,这个结构包含了设备的各种操作函数指针,如read、write、ioctl等。file_operations结构会随着内核版本的更新而有所变化,但其核心功能保持一致,...

    嵌入式设计及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 ...

    嵌入式Linux设备驱动程序开发 (1).pdf

    设备驱动程序可以分为字符设备驱动程序、块设备驱动程序和网络设备驱动程序等几种类型。 在嵌入式Linux操作系统中,设备驱动程序的开发需要遵循一定的规则和规范。首先,需要了解设备驱动程序的通用模块框架,即...

    Linux设备驱动,中文第二版

    网络设备驱动部分涵盖了网络协议栈的结构和网络驱动接口,包括接收和发送数据包、配置网络参数以及错误处理等。开发者将学习如何与协议栈交互,以实现高效的数据传输。 此外,书中还涉及了USB、PCI等总线的设备驱动...

    Linux设备驱动开发免费讲座教材

    2. **设备模型**:介绍Linux设备模型,如sysfs、udev等,以及设备分类(字符设备、块设备、网络设备等)和设备文件。 3. **驱动开发基础**:涵盖如何编写简单的字符设备驱动,包括打开、关闭、读写操作的实现,以及...

    Linux设备驱动程序第三版(中文版)

    该书详细介绍了Linux驱动程序的基本结构和设计原则,包括字符设备驱动、块设备驱动、网络设备驱动、中断处理、DMA传输、定时器和工作队列等核心概念。通过阅读,读者可以了解到如何编写设备的打开、关闭、读写等基本...

    嵌入式设计及Linux驱动开发指南:基于ARM9处理器随书光盘

    - **网络设备驱动**:负责网络通信功能。 - **中断处理机制**:中断是嵌入式系统中非常重要的概念,驱动程序需要正确处理中断事件。 #### 知识点五:随书光盘资源介绍 - **资源类型**:随书光盘通常包含以下几种...

Global site tag (gtag.js) - Google Analytics