第九章_Linux网络设备驱动程序

上传人:dfg****19 文档编号:246634138 上传时间:2024-10-15 格式:PPT 页数:29 大小:2.42MB
返回 下载 相关 举报
第九章_Linux网络设备驱动程序_第1页
第1页 / 共29页
第九章_Linux网络设备驱动程序_第2页
第2页 / 共29页
第九章_Linux网络设备驱动程序_第3页
第3页 / 共29页
点击查看更多>>
资源描述
IOTek Information Tchnology,*,Click to edit Master title style,IOTek Information Tchnology,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,Click to edit Master title style,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,IOTek Information Tchnology,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,Click to edit Master title style,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,IOTek Information Tchnology,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,Click to edit Master title style,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,IOTek Information Tchnology,*,Click to edit Master title style,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,单击此处编辑母版标题样式,*,Chapter,*,static void Main(string, args),Console.WriteLine(请输入一个字符串:); / 输入提示,/ 从控制台读入字符串,string,line,= Console.ReadLine();,/ 循环输出字符串中的字符,foreach (char c in,line,),Console.WriteLine(c);,Console.ReadLine();,static void Main(string, args),Console.WriteLine(请输入一个字符串:); / 输入提示,/ 从控制台读入字符串,string,line,= Console.ReadLine();,/ 循环输出字符串中的字符,foreach (char c in,line,),Console.WriteLine(c);,Console.ReadLine();,依次循环字符串中的每个字符,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,Linux,网络设备驱动程序,第,9,章,本章目标,了解,Linux,网络驱动程序的数据交换过程,掌握移植和编写具体网卡驱动程序的方法,本章结构,Linux,网络设备驱动程序,Linux,网络设备驱动的结构,网络设备的注册、注销和初始化,网络设备的打开和释放,数据包发送,数据包接收,网络连接状态,参数设置和统计数据,Linux,网络设备简介,网络设备,又叫网络接口是,Linux,第三类标准设备,网络设备和块设备类似,在内核的特定数据结构中注册自己,当发生网络数据交换时,网络设备驱动程序注册的方法将被内核调用,网络设备不会在,/dev,下存在一个设备入口,它使用保留的内部设备名,网络设备的特点,网络设备异步的接收外来的数据包,有别于其他设备,网络设备主动的“请求”将硬件获得的数据包压入内核,而其他设备例如块设备被“请求”向内核发送缓冲区,网络设备同时要执行大量的管理任务,设置地址,修改传输参数,维护流量和流量控制,错误统计和报告,网络设备的特点,网络子系统是完全与协议无关的,,网络驱动程序与内核其余部分之间的每次交互处理的都是一个网络数据包,9.1 Linux,网络设备驱动的结构,9.1.1,网络协议接口层,最主要的功能是给上层协议提供了透明的数据包发送和接收接口。,上层,ARP,或,IP,协议需要发送数据包时,调用网络协议接口层的,dev_queue_xmit(),函数,上层对数据包的接收也通过向,netif_rx(),函数,:,dev_queue_xmit(struct sk_buff *skb);,int netif_rx(struct sk_buff *skb);,9.1.1,网络协议接口层,套接字缓冲区,(sk_buff),结构,套接字缓冲区(,sk_buff,)结构是,Linux,内核网络子系统的核心内容,在,中被定义,sk_buff,结构中的重要字段,:,struct net_device *rx_dev;,struct net_device *dev;,union /* . */ h;,union /* . . . */ nh;,union /*. */ mac;,unsigned char *head;,unsigned char *data;,unsigned char *tail;,unsigned char *end;,unsigned long len;,unsigned char ip_summed;,unsigned char pkt_type,分别为接收和发送缓冲区的设备,指向数据包中各个层的数据包头。,h,指向传输层包头,,nh,指向网络层包头,,mac,指向链路层包头,用来寻址数据包中的数据指针。,head,指向已分配空间开头,,data,指向有效的,octet,开头,,tail,指向有效的,octet,结尾,而,end,指向,tail,可以到达的最大地址,PACKET_HOST,PACKET_BROADCAST,PACKET_MULTICAST,PACKET_OTHERHOST,9.1.1,网络协议接口层,struct sk_buff *alloc_skb(unsigned int len, int priority);,struct sk_buff *dev_alloc_skb(unsigned int len);,void kfree_skb(struct sk_buff *skb);,void dev_kfree_skb(struct sk_buff *skb);,unsigned char *skb_put(struct sk_buff *skb, int len);,unsigned char *_ _skb_put(struct sk_buff *skb, int len);,在缓冲区末尾添加数据,前一个函数会进行检查,释放套接字缓冲区,分配套接字缓冲区,9.1.1,网络协议接口层,unsigned char *skb_push(struct sk_buff *skb, int len);,unsigned char *_ _skb_push(struct sk_buff *skb, int len);,缓冲区头部添加数据,int skb_tailroom(struct sk_buff *skb);,void skb_reserve(struct sk_buff *skb, int len);,unsigned char *skb_pull(struct sk_buff *skb, int len);,int skb_headroom(struct sk_buff *skb);,返回缓冲区后部可用空间总量,返回缓冲区前面部分可用空间总量,在可填充缓冲区之前保留包头空间,从数据包头拿出数据,通常用来剥离数据包头,9.1.2,网络设备接口层,net_device,结构,该结构是网络设备驱动的核心,它包含了许多成员。,可以参考,文件,阅读它的完整定义。,net_device,结构可分为,全局成员,硬件相关成员,接口相关成员,设备方法成员,公用成员,9.1.2,网络设备接口层,net_device,结构的主要成员,全局信息,char nameIFNAMESIZ,int (*init)(struct net_device *dev),硬件信息,unsigned long rmem_end;,unsigned long rmem_start;,unsigned long mem_end;,unsigned long mem_start;,unsigned long base_addr;,unsigned char irq;,unsigned char if_port;,unsigned char dma;,如果被设置了,在,register_netdev,奖调用他初始化,net_device,结构,现代驱动一般在注册接口中完成初始化。,这些字段描述了设备共享内存的起止地址,描述设备的,I/O,基地址,描述设备中断号,描述多端口设备的活动端口,描述设备的,DMA,通道,9.1.2,网络设备接口层,接口信息,int (*open)(struct net_device *dev);,int (*stop)(struct net_device *dev);,int (*hard_start_xmit) (struct sk_buff *skb, struct net_device *dev);,int (*hard_header) (struct sk_buff *skb, struct net_device *dev, unsigned short type, void *daddr, void *saddr, unsigned len);,打开接口。当,ifconfig,激活网络设备时,接口被打开。通常我们在,open,方法里面完成资源的分配,包括,I/O,映射、中断注册、,DMA,注册等。同时激活硬件,并增加使用计数,停止接口。在这个方法里面,我们完成与,open,方法相反的,注销操作,该方法初始化数据包的传输。是网络设备驱动中非常重要的一个方法。我们将完整的数据包放入一个套接字缓冲区,sk_buff,结构里,根据先前检索到的源和目的硬件地址建立硬件头,9.1.2,网络设备接口层,int (*rebuild_header)(struct sk_buff *skb);,void (*tx_timeout)(struct net_device *dev);,struct net_device_stats *(*get_stats)(struct net_device *dev);,int (*set_config)(struct net_device *dev, struct ifmap *map);,int (*do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);,void (*set_multicast_list)(struct net_device *dev);,用来在传输数据包之前重建硬件头,数据包发送在超时时间内失败,这时该方法被调用。这个方法应该解决失败的问题并重新开始发送数据包,当应用程序需要获得接口的统计信息时,这个方法被调用,改变接口的配置。比如改变,I/O,端口和中断号等,现在的驱动程序通常无需该方法,实现设备自定义的,ioctl,命令,当设备的组播列表改变或设备标志改变时,该方法被调用,9.1.2,网络设备接口层,int (*set_mac_address)(struct net_device *dev, void *addr);,int (*change_mtu)(struct net_device *dev, int new_mtu);,int (*header_cache) (struct neighbour *neigh, struct hh_cache *hh);,int (*hard_header_parse) (struct sk_buff *skb, unsigned char *haddr);,int (*header_cache_update) (struct hh_cache *hh, struct net_device *dev, unsigned char *haddr);,如果接口支持,MAC,地址改变,则可以实现该函数,当接口的,MTU,改变时,该方法将被调用,负责做出相应的特定处理,根据,ARP,查询的结果填充,hh_cache,结构,在发生变化时,该方法更新,hh_cache,结构中的目的地址,从,skb,中包含的数据包中获得源地址,并将其复制到位于,haddr,的缓冲区中,9.2.1,网络设备的注册、注销,注册与注销函数,创建,net_device,释放,net_device,int register_netdev(struct net_device *dev);,void unregister_netdev(struct net_device *dev);,struct net_device *alloc_netdev(int sizeof_priv,const char *name,void (*setup)(struct net_device*);,struct net_device *alloc_etherdev(int sizeof_priv);,void free_netdev(struct net_device *dev);,9.2.1,网络设备的注册、注销,1 int xxx_init_module(void),2 ,3 ,4 /*,分配,net_device,结构体并对其成员赋值*,/,5 xxx_dev =,alloc_netdev,(sizeof(struct xxx_priv),“sn%d”, xxx_init);,6if(xxx_dev = NULL),7/*,分配,net_device,失败*,/,8,9/*,注册,net_device,结构体*,/,10if(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 ,9.3,网络设备的打开和释放,网络设备的打开函数完成如下工作:,使能设备使用的硬件资源,申请,I/O,区域、中断和,DMA,通道等。,调用,Linux,内核提供的,netif_start_queue(),函数,激活设备发送队列。,网络设备的关闭函数需要完成如下工作:,调用,Linux,内核提供的,netif_stop_queue(),函数,停止设备传输包。,释放设备所使用的,I/O,区域、中断和,DMA,资源。,netif_start_queue(),和,netif_stop_queue(),两个函数的原型,void netif_start_queue(struct net_device *dev);,void netif_stop_queue(struct net_device *dev);,9.3,网络设备的打开和释放,int xxx_open(struct net_device *dev),/*,申请端口、,IRQ,等,类似于,fops-open */,ret = request_irq(dev-irq, ,netif_start_queue(dev);,int xxx_release(struct net_device *dev),/*,释放端口、,IRQ,等,类似于,fops-close*/,free_irq(dev-irq, dev);,netif_stop_queue(dev); /*cant transmit any more*/,9.4,数据包发送,网络设备驱动完成数据包发送的流程如下:,网络设备驱动程序从上层协议传递过来的,sk_buff,参数获得数据包的有效数据和长度,将有效数据放入临时缓冲区。,对于以太网,如果有效数据的长度小于以太网冲突检测所要求数据帧的最小长度,ETH_ZLEN,,则给临时缓冲区的末尾填充,0,。,设置硬件的寄存器,驱使网络设备进行数据发送操作。,9.4,数据包发送,1 int xxx_tx(struct sk_buff *skb, struct net_device *dev),2 ,3 int len;,4 char *data, shortktETH_ZLEN;,5 /*,获得有效数据指针和长度*,/,6 data = skb-data;,7 len = skb-len;,8 if(len data, skb-len);,13 len = ETH_ZLEN;,14data = shortpkt;,15 ,17dev-trans_start = jiffies; /*,记录发送时间戳*,/,19 /*,设置硬件寄存器让硬件把数据包发送出去*,20xxx_hw_tx(data, len, dev);,21 ,22 ,9.4,数据包发送,传输超时处理,当数据传输超时时,意味着当前的发送操作失败,,此时,数据包发送超时处理函数,xxx_tx_timeout,将被调用。,这个函数需要调用,Linux,内核提供的,netif_wake_queue(),函数重新启动设备发送队列。如下所示:,1void xxx_tx_timeout(struct net_device *dev),2,3,4netif_ wake_queue(dev);/*,重新启动设备发送队列*,/,5,9.5,数据包接收,网络设备接收数据的主要方法,是由中断引发设备的中断处理函数,,中断处理函数判断中断类型,,如果为接收中断,则读取接收到的数据,分配,sk_buffer,数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区,并调用,netif_rx(),函数将,sk_buffer,传递给上层协议。,9.5,数据包接收,static void,xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs),switch(status & ISQ_EVENT_MASK),case ISQ_RECEIVER_EVENT:,/*,获取数据包*,/,xxx_rx,(dev);,break;,/*,其他类型的中断*,/,static void xxx_rx(struct xxx_device *dev),length = get_rev_len();,/*,分配新的套接字缓冲区*,/,skb = dev_alloc_skb(length + 2);,skb = reserve(skb, 2); /*,对齐*,/,skb-dev = dev;,/*,读取硬件上接收到的数据*,/,insw(ioaddr + RX_FRAME_PORT,skb_put(skb, length), length 1);,if(length & l),skb-datalength 1 =,inw(ioaddr + RX_FRAME_PORT);,/*,获取上层协议类型*,/,skb-protocol = eth_type_trans(skb, dev);,netif_rx(skb);,/*,把数据包交给上层*,/,dev-last_rx = jiffies;,/*,记录接收时间戳*,/,.,9.6,网络连接状态,网络适配器硬件电路可以检测出链路上是否有载波,载波反映了网络的连接是否正常。,网络设备驱动可以通过如下函数通知网络的连接状态:,网络设备驱动程序中往往设置一个定时器来对链路状态进行周期性地检查,当定时器到期之后,在定时器处理函数中读取物理设备的相关寄存器获得载波状态,从而更新设备的连接状态。,void netif_carrier_on(struct net_device *dev);,void netif_carrier_off(struct net_device *dev);,int netif_carrier_ok(struct net_device *dev);,9.7,参数设置和统计数据,参数设置通过,ioctl(),函数设置:,SIOCSIFHWADDR,命令设置,MAC,地址,SIOCSIFMAP,(如在控制台中运行网络配置命令,ifconfig,就会引发这一调用,),统计函数:,网络设备驱动的,get_stats,函数模板,统计信息什么时候进行统计?,主要在接收和发送数据包的时候进行统计。,1 struct net_device_stats *xxx_stats(struct net_device *dev),2 ,3 struct xxx_priv *priv = netdev_priv(dev);,4 return ,5 ,本章总结,net_device,结构体和,sk_buf,结构体,Linux,网络设备驱动程序,Linux,网络设备驱动的结构,网络设备的注册、注销和初始化,网络设备的打开和释放,数据包发送,数据包接收,网络连接状态,参数设置和统计数据,注册和注销函数,数据包发送方法,用中断接收数据方法,实验,任务,1,:,移植,CS8900A,网卡驱动,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 机械制造 > 工业自动化


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!