专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »嵌入式开发 » linux驱动开发:Linux驱动的开发1【转载】 »正文

linux驱动开发:Linux驱动的开发1【转载】

来源: 发布时间:星期四, 2008年12月11日 浏览:9次 评论:0
=tf width="98%" align=center border=0>
=bw width="100%">=htd id=font_word style="FONT-SIZE: 14px; FONT-FAMILY: 宋体, Verdana, Arial, Helvetica, sans-ser">作需要写了我们公司块网卡Linux驱动经历个从无到有过程深感技术 
oqLfbaiducukL7K
oqLfbaiducukL7K交流重要Linux作为挑战微软垄断强有力武器日益受到大家喜爱真希望她能 
oqLfbaiducukL7K
oqLfbaiducukL7K在中国迅速成长文档贴出来希望和大家探讨Linux技术和应用促进Linux在 
oqLfbaiducukL7K
oqLfbaiducukL7K中国普及 
oqLfbaiducukL7K
oqLfbaiducukL7KLinux操作系统网络驱动编写 
oqLfbaiducukL7K
oqLfbaiducukL7K.Linux系统设备驱动概述 
oqLfbaiducukL7K
oqLfbaiducukL7K1.1 Linux设备驱动分类 
oqLfbaiducukL7K
oqLfbaiducukL7K1.2 编写驱动些基本概念 
oqLfbaiducukL7K
oqLfbaiducukL7K二.Linux系统网络设备驱动 
oqLfbaiducukL7K
oqLfbaiducukL7K2.1 网络驱动结构 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2 网络驱动基本方法 
oqLfbaiducukL7K
oqLfbaiducukL7K2.3 网络驱动中用到数据结构 
oqLfbaiducukL7K
oqLfbaiducukL7K2.4 常用系统支持 
oqLfbaiducukL7K
oqLfbaiducukL7K三.编写Linux网络驱动中可能遇到问题 
oqLfbaiducukL7K
oqLfbaiducukL7K3.1 中断共享 
oqLfbaiducukL7K
oqLfbaiducukL7K3.2 硬件发送忙时处理 
oqLfbaiducukL7K
oqLfbaiducukL7K3.3 流量控制(flow control) 
oqLfbaiducukL7K
oqLfbaiducukL7K3.4 调试 
oqLfbaiducukL7K
oqLfbaiducukL7K四.进阅读 
oqLfbaiducukL7K
oqLfbaiducukL7K五.杂项 
oqLfbaiducukL7K
oqLfbaiducukL7K.Linux系统设备驱动概述 
oqLfbaiducukL7K
oqLfbaiducukL7K1.1 Linux设备驱动分类 
oqLfbaiducukL7K
oqLfbaiducukL7KLinux设备驱动在Linux内核源代码中占有很大比例源代码长度日益增加 
oqLfbaiducukL7K
oqLfbaiducukL7K主要是驱动增加在Linux内核不断升级过程中驱动结构还是相对稳定 
oqLfbaiducukL7K
oqLfbaiducukL7K在2.0.xx到2.2.xx变动里驱动编写做了些改变但是从2.0.xx驱动到 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.xx移植只需做少量工作 
oqLfbaiducukL7K
oqLfbaiducukL7KLinux系统设备分为设备(char device)块设备(block device)和网络设备(net 
oqLfbaiducukL7K
oqLfbaiducukL7Kwork device)三种设备是指存取时没有缓存设备块设备读写都有缓存来支 
oqLfbaiducukL7K
oqLfbaiducukL7K持并且块设备必须能够随机存取(random access)设备则没有这个要求典型 
oqLfbaiducukL7K
oqLfbaiducukL7K设备包括鼠标键盘串行口等块设备主要包括硬盘软盘设备CD-ROM等个 
oqLfbaiducukL7K
oqLfbaiducukL7K文件系统要安装进入操作系统必须在块设备上 
oqLfbaiducukL7K
oqLfbaiducukL7K网络设备在Linux里做专门处理Linux网络系统主要是基于BSD unix机制 
oqLfbaiducukL7K
oqLfbaiducukL7K在系统和驱动之间定义有专门数据结构(sk_buff)进行数据传递系统里支持 
oqLfbaiducukL7K
oqLfbaiducukL7K对发送数据和接收数据缓存提供流量控制机制提供对多协议支持 
oqLfbaiducukL7K
oqLfbaiducukL7K1.2 编写驱动些基本概念 
oqLfbaiducukL7K
oqLfbaiducukL7K无论是什么操作系统驱动都有些通用概念操作系统提供给驱动支 
oqLfbaiducukL7K
oqLfbaiducukL7K持也大致相同下面简单介绍下网络设备驱动些基本要求 
oqLfbaiducukL7K
oqLfbaiducukL7K1.2.1 发送和接收 
oqLfbaiducukL7K
oqLfbaiducukL7K这是个网络设备最基本功能块网卡所做无非就是收发工作所以驱动里 
oqLfbaiducukL7K
oqLfbaiducukL7K要告诉系统你发送在哪里系统在有数据要发送时就会发 送还有 
oqLfbaiducukL7K
oqLfbaiducukL7K驱动由于是直接操纵硬件所以网络硬件有数据收到最先能得到这个数据也就 
oqLfbaiducukL7K
oqLfbaiducukL7K是驱动它负责把这些原始数据进行必要处理然后送给系统这里操作系统必 
oqLfbaiducukL7K
oqLfbaiducukL7K须要提供两个机制个是找到驱动发送个是驱动把收到数据送 
oqLfbaiducukL7K
oqLfbaiducukL7K给系统 
oqLfbaiducukL7K
oqLfbaiducukL7K1.2.2 中断 
oqLfbaiducukL7K
oqLfbaiducukL7K中断在现代计算机结构中有重要地位操作系统必须提供驱动响应中断能力 
oqLfbaiducukL7K
oqLfbaiducukL7K般是把个中断处理注册到系统中去操作系统在硬件中断发生后 驱动 
oqLfbaiducukL7K
oqLfbaiducukL7K处理Linux支持中断共享即多个设备共享个中断 
oqLfbaiducukL7K
oqLfbaiducukL7K1.2.3 时钟 
oqLfbaiducukL7K
oqLfbaiducukL7K在实现驱动很多地方会用到时钟如某些协议里超时处理没有中断机制 
oqLfbaiducukL7K
oqLfbaiducukL7K硬件轮询等操作系统应为驱动提供定时机制般是在预定时 间过了以后回 
oqLfbaiducukL7K
oqLfbaiducukL7K调注册时钟在网络驱动如果硬件没有中断功能定时器可以提供轮询 
oqLfbaiducukL7K
oqLfbaiducukL7K(poll)方式对硬件进行存取或者是实现某些协议时需要超时重传等 
oqLfbaiducukL7K
oqLfbaiducukL7K二.Linux系统网络设备驱动 
oqLfbaiducukL7K
oqLfbaiducukL7K2.1 网络驱动结构 
oqLfbaiducukL7K
oqLfbaiducukL7K所有Linux网络驱动遵循通用接口设计时采用是面向对象方法个设备 
oqLfbaiducukL7K
oqLfbaiducukL7K就是个对象(device 结构)它内部有自己数据和方法个设备方法被时 
oqLfbaiducukL7K
oqLfbaiducukL7K个参数都是这个设备对象本身这样这个方法就可以存取自身数据(类似面向对 
oqLfbaiducukL7K
oqLfbaiducukL7K象设计时this引用) 
oqLfbaiducukL7K
oqLfbaiducukL7K个网络设备最基本方法有化、发送和接收 
oqLfbaiducukL7K
oqLfbaiducukL7K------------------- --------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K|deliver packets | |receive packets queue| 
oqLfbaiducukL7K
oqLfbaiducukL7K|(dev_queue_xmit) | |them(net_rx) | 
oqLfbaiducukL7K
oqLfbaiducukL7K------------------- --------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K| | / 
oqLfbaiducukL7K
oqLfbaiducukL7K/ | | 
oqLfbaiducukL7K
oqLfbaiducukL7K------------------------------------------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K| methods and variables(initialize,open,close,hard_xmit,| 
oqLfbaiducukL7K
oqLfbaiducukL7K| errupt handler,config,resources,status...) | 
oqLfbaiducukL7K
oqLfbaiducukL7K------------------------------------------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K| | / 
oqLfbaiducukL7K
oqLfbaiducukL7K/ | | 
oqLfbaiducukL7K
oqLfbaiducukL7K----------------- ---------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K|send to hardware | |receivce from hardware| 
oqLfbaiducukL7K
oqLfbaiducukL7K----------------- ---------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K| | / 
oqLfbaiducukL7K
oqLfbaiducukL7K/ | | 
oqLfbaiducukL7K
oqLfbaiducukL7K----------------------------------------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K| hardware media | 
oqLfbaiducukL7K
oqLfbaiducukL7K----------------------------------------------------- 
oqLfbaiducukL7K
oqLfbaiducukL7K完成硬件化、device中变量化和系统资源申请发送是 
oqLfbaiducukL7K
oqLfbaiducukL7K在驱动上层协议层有数据要发送时自动般驱动中不对发送数据进 
oqLfbaiducukL7K
oqLfbaiducukL7K行缓存而是直接使用硬件发送功能把数据发送出去接收数据般是通过硬件中断 
oqLfbaiducukL7K
oqLfbaiducukL7K来通知在中断处理把硬件帧信息填入个skbuff结构中然后net
oqLfbaiducukL7K
oqLfbaiducukL7Krx传递给上层处理 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2 网络驱动基本方法 
oqLfbaiducukL7K
oqLfbaiducukL7K网络设备做为个对象提供些方法供系统访问正是这些有统接口方法掩蔽 
oqLfbaiducukL7K
oqLfbaiducukL7K了硬件具体细节让系统对各种网络设备访问都采用统形式做到硬件无关性 
oqLfbaiducukL7K
oqLfbaiducukL7K 
oqLfbaiducukL7K
oqLfbaiducukL7K下面解释最基本方法 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.1 化(initialize) 
oqLfbaiducukL7K
oqLfbaiducukL7K驱动必须有化方法在把驱动载入系统时候会这个 
oqLfbaiducukL7K
oqLfbaiducukL7K它做以下几方面工作检测设备里你可以根据硬件特征检查硬件 
oqLfbaiducukL7K
oqLfbaiducukL7K是否存在然后决定是否启动这个驱动配置和化硬件里你可 
oqLfbaiducukL7K
oqLfbaiducukL7K以完成对硬件资源配置比如即插即用硬件就可以在这个时候进行配置(Linux内核 
oqLfbaiducukL7K
oqLfbaiducukL7K对PnP功能没有很好支持可以在驱动里完成这个功能)配置或协商好硬件占用 
oqLfbaiducukL7K
oqLfbaiducukL7K资源以后就可以向系统申请这些资源有些资源是可以和别设备共享如中断 
oqLfbaiducukL7K
oqLfbaiducukL7K有些是不能共享如IO、DMA接下来你要化device结构中变量最后你可 
oqLfbaiducukL7K
oqLfbaiducukL7K以让硬件正式开始工作 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.2 打开(open) 
oqLfbaiducukL7K
oqLfbaiducukL7Kopen这个方法在网络设备驱动里是网络设备被激活时候被(即设备状态由dow 
oqLfbaiducukL7K
oqLfbaiducukL7Kn-->up)所以实际上很多在initialize中工作可以放到这里来做比如资源申请 
oqLfbaiducukL7K
oqLfbaiducukL7K硬件激活如果dev->open返回非0(error)则硬件状态还是down 
oqLfbaiducukL7K
oqLfbaiducukL7Kopen方法另个作用是如果驱动做为个模块被装入则要防止模块卸载时设备处 
oqLfbaiducukL7K
oqLfbaiducukL7K于打开状态在open方法里要MOD_INC_USE_COUNT宏 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.3 关闭(stop) 
oqLfbaiducukL7K
oqLfbaiducukL7Kclose方法做和open相反工作可以释放某些资源以减少系统负担close是在设备状 
oqLfbaiducukL7K
oqLfbaiducukL7K态由up转为down时被另外如果是做为模块装入驱动close里应该
oqLfbaiducukL7K
oqLfbaiducukL7KOD_DEC_USE_COUNT减少设备被引用次数以使驱动可以被卸载 
oqLfbaiducukL7K
oqLfbaiducukL7K另外close方法必须返回成功(0success) 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.4 发送(hard_start_xmit) 
oqLfbaiducukL7K
oqLfbaiducukL7K所有网络设备驱动都必须有这个发送方法在系统驱动xmit时发送 
oqLfbaiducukL7K
oqLfbaiducukL7K数据放在个sk_buff结构中驱动把数据传给硬件发出去也有些特殊 
oqLfbaiducukL7K
oqLfbaiducukL7K设备比如loopback把数据组成个接收数据再回送给系统或者dummy设备直接丢弃数 
oqLfbaiducukL7K
oqLfbaiducukL7K据 
oqLfbaiducukL7K
oqLfbaiducukL7K如果发送成功hard_start_xmit方法里释放sk_buff返回0(发送成功)如果设备暂时 
oqLfbaiducukL7K
oqLfbaiducukL7K无法处理比如硬件忙则返回1这时如果dev->tbusy置为非0则系统认为硬件忙 
oqLfbaiducukL7K
oqLfbaiducukL7K要等到dev->tbusy置0以后才会再次发送tbusy置0任务般由中断完成硬件在发送 
oqLfbaiducukL7K
oqLfbaiducukL7K结束后产生中断这时可以把tbusy置0然后用mark_bh通知系统可以再次发送 
oqLfbaiducukL7K
oqLfbaiducukL7K在发送不成功情况下也可以不置dev->tbusy为非0这样系统会不断尝试重发如果 
oqLfbaiducukL7K
oqLfbaiducukL7Khard_start_xmit发送不成功则不要释放sk_buff传送下来sk_buff中数据已经包 
oqLfbaiducukL7K
oqLfbaiducukL7K含硬件需要帧头所以在发送方法里不需要再填充硬件帧头数据可以直接提交给硬 
oqLfbaiducukL7K
oqLfbaiducukL7K件发送sk_buff是被锁住(locked)确保其他不会存取它 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.5 接收(reception) 
oqLfbaiducukL7K
oqLfbaiducukL7K驱动并不存在个接收方法有数据收到应该是驱动来通知系统般设备 
oqLfbaiducukL7K
oqLfbaiducukL7K收到数据后都会产生个中断在中断处理中驱动申请块sk_buff(skb)从 
oqLfbaiducukL7K
oqLfbaiducukL7K硬件读出数据放置到申请好缓冲区里接下来填充sk_buff中 些信息skb->dev 
oqLfbaiducukL7K
oqLfbaiducukL7K = dev判断收到帧协议类型填入skb->protocol(多协 议支持)把指针skb->m 
oqLfbaiducukL7K
oqLfbaiducukL7Kac.raw指向硬件数据然后丢弃硬件帧头(skb_pull)还要设置skb->pkt_type标明第二 
oqLfbaiducukL7K
oqLfbaiducukL7K层(链路层)数据类型可以是以下类型: 
oqLfbaiducukL7K
oqLfbaiducukL7KPACKET_BROADCAST : 链路层广播 
oqLfbaiducukL7K
oqLfbaiducukL7KPACKET_MULTICAST : 链路层组播 
oqLfbaiducukL7K
oqLfbaiducukL7KPACKET_SELF : 发给自己帧 
oqLfbaiducukL7K
oqLfbaiducukL7KPACKET_OTHERHOST : 发给别人帧(监听模式时会有这种帧) 
oqLfbaiducukL7K
oqLfbaiducukL7K最后net_rx把数据传送给协议层net_rx里数据放入处理队列然后返回 
oqLfbaiducukL7K
oqLfbaiducukL7K真正处理是在中断返回以后这样可以减少中断时间net_rx以后 
oqLfbaiducukL7K
oqLfbaiducukL7K驱动就不能再存取数据缓冲区skb 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.6 硬件帧头(hard_header) 
oqLfbaiducukL7K
oqLfbaiducukL7K硬件般都会在上层数据发送之前加上自己硬件帧头比如以太网(Ethernet)就有14 
oqLfbaiducukL7K
oqLfbaiducukL7K字节帧头这个帧头是加在上层ip、ipx等数据包前面驱动提供个hard_ 
oqLfbaiducukL7K
oqLfbaiducukL7Kheader方法协议层(ip、ipx、arp等)在发送数据之前会这段 
oqLfbaiducukL7K
oqLfbaiducukL7K硬件帧头长度必须填在dev->hard_header_len这样协议层回在数据之前保留好硬件 
oqLfbaiducukL7K
oqLfbaiducukL7K帧头空间这样hard_header只要skb_push然后正确填入硬件帧头就可以了 
oqLfbaiducukL7K
oqLfbaiducukL7K  
oqLfbaiducukL7K
oqLfbaiducukL7K在协议层hard_header时传送参数包括(2.0.xx):数据sk_buffdevice指针 
oqLfbaiducukL7K
oqLfbaiducukL7Kprotocol地址(daddr)源地址(saddr)数据长度(len)数据长度不要使用s 
oqLfbaiducukL7K
oqLfbaiducukL7Kk_buff中参数hard_header时数据可能还没完全组织好saddr是NULL话 
oqLfbaiducukL7K
oqLfbaiducukL7K是使用缺省地址(default)daddr是NULL表明协议层不知道硬件目地址如果hard_h 
oqLfbaiducukL7K
oqLfbaiducukL7Keader完全填好了硬件帧头则返回添加字节数如果硬件帧头中信息还不完全(比 
oqLfbaiducukL7K
oqLfbaiducukL7K如daddr为NULL但是帧头中需要目硬件地址典型情况是以太网需要地址解析(ar 
oqLfbaiducukL7K
oqLfbaiducukL7Kp))则返回负字节数hard_header返回负数情况下协议层会做进build he 
oqLfbaiducukL7K
oqLfbaiducukL7Kader工作目前Linux系统里就是做arp (如果hard_header返回正dev->arp=1表明 
oqLfbaiducukL7K
oqLfbaiducukL7K不需要做arp返回负dev->arp=0做arp) 
oqLfbaiducukL7K
oqLfbaiducukL7K对hard_header在每个协议层处理如ip_output 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.7 地址解析(xarp) 
oqLfbaiducukL7K
oqLfbaiducukL7K有些网络有硬件地址(比如Ethernet)并且在发送硬件帧时需要知道目硬件地址这 
oqLfbaiducukL7K
oqLfbaiducukL7K样就需要上层协议地址(ip、ipx)和硬件地址对应这个对应是通过地址解析完成 
oqLfbaiducukL7K
oqLfbaiducukL7K需要做arp设备在发送之前会驱动rebuild_header方法主要参数 
oqLfbaiducukL7K
oqLfbaiducukL7K包括指向硬件帧头指针协议层地址如果驱动能够解析硬件地址就返回1如 
oqLfbaiducukL7K
oqLfbaiducukL7K果不能返回0 
oqLfbaiducukL7K
oqLfbaiducukL7K对rebuild_header在net/core/dev.cdo_dev_queue_xmit 
oqLfbaiducukL7K
oqLfbaiducukL7K2.2.8 参数设置和统计数据 
oqLfbaiducukL7K
oqLfbaiducukL7K在驱动里还提供些方法供系统对设备参数进行设置和读取信息般只有超级 
oqLfbaiducukL7K
oqLfbaiducukL7K用户(root)权限才能对设备参数进行设置设置方法有: 
oqLfbaiducukL7K
oqLfbaiducukL7Kdev->_mac_address 
oqLfbaiducukL7K
oqLfbaiducukL7K当用户ioctl类型为SIOCSIFHWADDR时是要设置这个设备mac地址般对mac地址 
oqLfbaiducukL7K
oqLfbaiducukL7K设置没有太大意义 
oqLfbaiducukL7K
oqLfbaiducukL7Kdev->_config 
oqLfbaiducukL7K
oqLfbaiducukL7K当用户ioctl时类型为SIOCSIFMAP时系统会驱动_config方法用户 
oqLfbaiducukL7K
oqLfbaiducukL7K会传递map结构包含需要I/O、中断等参数 
oqLfbaiducukL7K
oqLfbaiducukL7Kdev->do_ioctl 
oqLfbaiducukL7K
oqLfbaiducukL7K如果用户ioctl时类型在SIOCDEVPRIVATE和SIOCDEVPRIVATE+15之间系统会驱 
oqLfbaiducukL7K
oqLfbaiducukL7K动这个方法般是设置设备专用数据 
oqLfbaiducukL7K
oqLfbaiducukL7K读取信息也是通过ioctl进行除次之外驱动还可以提供个 
oqLfbaiducukL7K
oqLfbaiducukL7Kdev->get_stats方法返回个enet_statistics结构包含发送接收统计信息ioc 
oqLfbaiducukL7K
oqLfbaiducukL7Ktl处理在net/core/dev.cdev_ioctl和dev_sioc 
oqLfbaiducukL7K
[email protected] 

相关文章

读者评论

  • 共0条 分0页

发表评论

  • 昵称:
  • 内容: