⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 (ldd) ch14-网络驱动程序(下)(转载).htm

📁 html格式
💻 HTM
📖 第 1 页 / 共 4 页
字号:
      <P>raw,从包数据中删去硬件包头,并设置skb-&gt;pkt_type。最后一项在skb分配时缺省为PA<BR>CKET_HOST(表明包被指向这个主机),当然它也可以改为符合以太网目的地址得其它值<BR>。<BR>&nbsp;<BR>如果你的接口是点到点连接,你将无法收到未想到的选播包。为避免这个,你必须记住<BR>那些第一个八元组的最低位(LSB)是0的目的地址将被指向单个主机(也就是说,它是P<BR>ACKET_HOST或PACKET_OTHERHOST)。plip驱动程序用0xfc作为它的硬件地址的第一个八<BR>元组,而snull用0x00。这两个地址都导致一个可工作的以太网类的点到点连接。<BR>&nbsp;<BR>非以太网包头<BR>&nbsp;<BR>这节简要地介绍硬件包头是如何用来封装相关信息的。如果你希望了解细节,你可以从<BR>核心源码或特别传输介质的技术文档中得到。我们刚才已经看到硬件包头除了含有目的<BR>地址外,还有一些信息,其中最重要的是通信协议。<BR>&nbsp;<BR>不过,并不是每个协议都要提供所有的信息。象plip或snull之类的点到点连接可以避免<BR>传送整个以太网包头,同时不失去一般性。hard_header设备方法从核心接收传送信息--<BR>--包括协议级和硬件地址。它也收到16位的协议号。例如IP由ETH_P_IP标志。驱动程序<BR>应能正确地象接收主机传送包数据和协议号。点到点连接可以在硬件包头中省略地址,<BR>只传送协议号,因为传送是有保证的,与源和目的地址无关。一个只有IP的连接甚至什<BR>么硬件头都不传送。两种情况下,所有的工作都由hard_header完成,rebuild_header除<BR>了返回0外什么都不做。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>当包在连接的另一端被捡起时,接收函数将正确地设置skb-&gt;protocol,skb-&gt;pkt_type<BR>,和skb-&gt;mac.raw。<BR>&nbsp;<BR>skb-&gt;mac.raw是一个被网络高层代码实现的地址解析机制使用的字符指针(例如,net/i<BR>pv4/arp.c)。它必须指向一个与dev-&gt;type匹配的机器地址。设备类型的可能值被定义<BR>在&lt;linux/if_arp.h&gt;;以太网接口用ARPHRD_ETHER。例如,下面是eth_type_trans处理<BR>收到包的以太网包头的方法:<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skb-&gt;mac.raw=skb-&gt;data;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;skb_pull(skb,&nbsp;dev-&gt;hard_header_len);<BR>&nbsp;<BR>在最简单的情况下(无包头的点到点连接),skb-&gt;mac.raw可以指向一个含有这个接口<BR>的硬件地址的静态缓冲区,protocol可以被置为ETH_P_IP,packet_type仍维持其缺省值<BR>PACKET_HOST。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>加载时配置<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>用户可以用几个标准的关键字来配置接口。任何新的网络模块都应遵循这个标准:<BR>&nbsp;<BR>io=<BR>&nbsp;<BR>为接口设置I/O端口的基地址。如果系统中安装了不只一个接口,那么可以用一个由逗号<BR>分隔的列表来指定。<BR>&nbsp;<BR>irq=<BR>&nbsp;<BR>设置中断号。和上面一样,可以指定不止一个值。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>换句话说,一个装了两个own_eth接口的Linux用户可能用下面的命令行来加载模块:<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insmod&nbsp;own_eth.o&nbsp;io=0x300,&nbsp;0x320&nbsp;irq=5,7<BR>&nbsp;<BR>如果指定0值,那么io=和irq=选项都要被探测。因此用户可以通过指定io=0来强制探测<BR>。如果用户名优指定任何选项,多数驱动程序通常都探测一个接口,但有时,模块可能<BR>被禁止探测。(见ne.c中关于NE2000设备的探测)。<BR>&nbsp;<BR>设备驱动程序应该象刚才描述的这样工作。ISA设备的典型实现如下所示,假设驱动程序<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>设备驱动程序应该象刚才描述的这样工作。ISA设备的典型实现如下所示,假设驱动程序<BR>最多可以支持四个接口:<BR>&nbsp;<BR>(代码331)<BR>&nbsp;<BR>这段代码缺省探测一个板子,并总是自动探测中断,但用户可以改变这种行为。例如,i<BR>o=0,0,0将探测三块板子。<BR>&nbsp;<BR>除了使用io和irq外,驱动程序的作者可以随意增加其它加载时配置参数。也没有已建立<BR>的命名标准。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>运行时配置<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>用户有时可能希望在运行时改变接口的配置。例如,当中断号无法探测时,想对它正确<BR>配置的唯一办法就是“尝试—错误”技术。一个用户空间的程序可以获取设备的当前配<BR>置,并通过在一个打开的套接字上调用ioctl来设置一个新的配置。例如,应用ifconfig<BR>使用ioctl为接口设置I/O端口。<BR>&nbsp;<BR>我们前面知道一个为网络接口定义的方法中的一个是set_config。这个方法被用来在运<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>我们前面知道一个为网络接口定义的方法中的一个是set_config。这个方法被用来在运<BR>行时设置或改变一些接口特征。<BR>&nbsp;<BR>当一个程序询问当前配置时,核心从结构device中抽取相关信息,而不通知驱动程序;<BR>另一方面,当一个新的配置被传递给接口时,set_config被调用,这样驱动程序就可以<BR>检查这些值并采取相应的动作。这个驱动程序方法对应下面的原形:<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;(*set_config)(struct&nbsp;device&nbsp;*dev,&nbsp;struct&nbsp;ifmap&nbsp;*map);<BR>&nbsp;<BR>map参数指向一个由用户程序传递的结构的拷贝;这个拷贝已经在核心空间,所以驱动程<BR>序不需要调用memcpy_from&nbsp;_fs。<BR>&nbsp;<BR>结构ifmap的域是:<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;mem_start;<BR>&nbsp;<BR>unsigned&nbsp;long&nbsp;mem_end;<BR>&nbsp;<BR>unsigned&nbsp;short&nbsp;base_addr;<BR>&nbsp;<BR>unsigned&nbsp;char&nbsp;irq;<BR>&nbsp;<BR>unsigned&nbsp;char&nbsp;dma;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>unsigned&nbsp;char&nbsp;dma;<BR>&nbsp;<BR>这些域对应着结构device中的域。<BR>&nbsp;<BR>Unsigned&nbsp;char&nbsp;prot;<BR>&nbsp;<BR>这个域对应着dev中的if_port。map-&gt;port的含义是设备特定的。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>当一个进程为设备发出ioctl(SIOCSIFMAP)(即Socket&nbsp;I/O&nbsp;Control&nbsp;Set&nbsp;InterFace<BR>MAP)时,set_config设备方法被调用。这个进程在时强制使用新值之前,应该发出ioctl<BR>(SIOCGIFMAP)(即Socket&nbsp;I/O&nbsp;Control&nbsp;Get&nbsp;InterFace&nbsp;MAP),这样驱动程序只需要查看d<BR>ev和ifmap结构不匹配的地方。Map中任何不被驱动程序使用的域均可以略过。例如,一<BR>个不使用DMA的网络设备可以忽略map-&gt;dma。<BR>&nbsp;<BR>snull实现被设计成可以显示驱动程序是如何针对配置改变而动作的。对snull来说,没<BR>有一个域由物理意义。但出于说明的目的,代码禁止改变I/O地址,允许改变IRQ号,并<BR>忽略其它选项,从而显示这些改变是如何被响应、拒绝、或是忽略的。<BR>&nbsp;<BR>(代码333&nbsp;#1)<BR>&nbsp;<BR>这个方法的返回值被作为发出的ioctl系统调用的返回值,对于没有实现set_config的驱<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>这个方法的返回值被作为发出的ioctl系统调用的返回值,对于没有实现set_config的驱<BR>动程序则返回-EOPNOTSUPP。<BR>&nbsp;<BR>如果你对接口配置如何从用户空间访问感到好奇,请看misc-progs/netifconfig.c,它<BR>可以用来与set_config比较。下面是一个示例运行的输出:<BR>&nbsp;<BR>(代码333&nbsp;#2)<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>自定义ioctl命令<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>我们已经看到ioctl系统调用是为套接字实现的。SIOCSIFADDR和SIOCSIFMAP是“套接字i<BR>octl”的例子现在让我们看看这个系统调用的第三个参数是如何被网络代码使用的。<BR>&nbsp;<BR>当ioctl系统调用在套接字上被调用时,其命令号是在&lt;linux/sockios.h&gt;定义的符号之<BR>一,并且函数sock_ioctl直接调用一个协议特定的函数(这里协议指使用的主要网络协<BR>议,如IP或AppleTalk)。<BR>&nbsp;<BR>任何协议层不认识的ioctl命令被传递给设备层。这些设备相关的ioctl命令从用户空间<BR>接收第三个参数,即结构ifreq*;这个结构在&lt;linux/if.h&gt;中定义。SIOCSIFADDR和SIOC<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>接收第三个参数,即结构ifreq*;这个结构在&lt;linux/if.h&gt;中定义。SIOCSIFADDR和SIOC<BR>SIFMAP命令实际上是工作在ifreq结构上。SIOCSIFMAP的额外参数,尽管定义为ifmap,<BR>是ifreq的一个域。<BR>&nbsp;<BR>除了使用标准的调用,每个接口可以定义它自己的ioctl命令。例如plip接口允许通过io<BR>ctl修改其内部超时值。套接字的ioctl实现将16个命令看作对接口是私有的:从SIOCDEV<BR>PRIVATE到SIOCDEVPRIVATE+15。<BR>&nbsp;<BR>当这些命令中的一个被认识时,dev-&gt;do_ioctl在相关的接口驱动程序里被调用。这个函<BR>数接收与通用目的的ioctl函数使用的一样的ifreq*指针。<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Int&nbsp;(*do_ioctl)(struct&nbsp;device&nbsp;*dev,&nbsp;struct&nbsp;ifreq&nbsp;*ifr,&nbsp;int&nbsp;cmd);<BR>&nbsp;<BR>Ifr指针指向核心空间的一个地址,放有被用户传来结构的一个拷贝。在do_ioctl返回后<BR>,这个结构又被拷贝回用户空间;这样,驱动程序可以使用私有命令来接收和返回数据<BR>。<BR>&nbsp;<BR>设备特定的命令可以选择使用结构ifreq中的域,但它们已经带有标准的含义,驱动程序<BR>不太可能根据自己的需要适配这个结构。域ifr_data是个caddr_t项(一个指针),用于<BR>设备特定的需要。驱动程序和调用ioctl命令的程序应在ifr_data的使用上取得一致。例<BR>如,pppstats使用设备特定的命令来从ppp接口驱动程序中获取信息。<BR>&nbsp;<BR>在这里不值得给出do_ioctl的一个实现,但根据本章的信息和核心的例子,你应能在需<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>在这里不值得给出do_ioctl的一个实现,但根据本章的信息和核心的例子,你应能在需<BR>要的时候写出一个。不过注意,plip实现不正确地使用了ifr_data,不应做为ioctl实现<BR>的一个例子。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>统计信息<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>一个驱动程序需要的最后一个方法是get_stats。这个方法返回指向设备统计信息的一个<BR>指针。它的实现相当容易:<BR>&nbsp;<BR>(代码335)<BR>&nbsp;<BR>返回有意义的统计信息所需的实际工作散布在驱动程序中,不同的域分别被更新。下表<BR>给出enet_statistics结构中最有趣的几个域。<BR>&nbsp;<BR>int&nbsp;rx_packets;<BR>&nbsp;<BR>int&nbsp;tx_packets;<BR>&nbsp;<BR>这两个域含有接口成功传送的进来和外出包的总数。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>这两个域含有接口成功传送的进来和外出包的总数。<BR>&nbsp;<BR>int&nbsp;rx_errors;<BR>&nbsp;<BR>int&nbsp;tx_errors;<BR>&nbsp;<BR>出错的接收和发送的数目。接收错可能是错误的校验和、错误的包大小,以及其它问题<BR>的结果。发送错误不太常见,一般都是线缆的问题。<BR>&nbsp;<BR>int&nbsp;rx_dropped;<BR>&nbsp;<BR>int&nbsp;tx_dropped;<BR>&nbsp;<BR>在接收和发送时被丢弃的包的个数。当包数据没有可用内存时,包便被丢弃了。tx_drop<BR>ped很少使用。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>这个结构还有几个域,可以用来细分发送和接收时发生的错误。感兴趣的读者可以看&lt;li<BR>nux/if_ether.h&gt;中结构的定义。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>选播<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>“选播”包是指一个网络包,它将要被多于一个,但又不是全部的主机接收。<BR>&nbsp;<BR>这个功能是通过给一组主机赋以特殊的硬件地址来获得的。指向这些特殊地址中的一个<BR>的包将被这个组中所有的主机收到。在以太网的情况下,一个选播地址是将目的地址中<BR>第一个八元组的最低位设置而得到,而所有的设备板子都在其硬件地址中将这一位清除<BR>。<BR>&nbsp;<BR>处理主机组以及硬件地址的棘手部分都有应用或核心完成了,接口驱动程序并不需要处<BR>理这些问题。<BR>&nbsp;<BR>选播包的发送很简单,与其它包完全一样。接口在传输介质上发送它们,根本不管目的<BR>地址。核心必须设置一个正确的硬件目的地址;rebuild_header设备方法(如果被定义<BR>)并不需要查看它整理的数据。<BR>&nbsp;<BR>而另一方面,接收选播包需要设备的一些合作。当一个“有趣的”选播包被收到时(也<BR>就是一个包的目的地址确定一组主机,其中包含了这个接口),硬件应该通知操作系统<BR>。这意味着硬件过滤器应被设计为能够区别不同的选播地址。这个过滤器在接口的一般<BR>操作中,将网络包的地址与其自己的硬件地址进行匹配。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>操作中,将网络包的地址与其自己的硬件地址进行匹配。<BR>&nbsp;<BR>典型地,在考虑选播的情况下,硬件可分为一下三类:<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;不能处理选播的接口。这类接口要么接收指向自己硬件地址的包(包括播送<BR>包),要么节收所有的包。它们接收选播包是通过接收所有的包实现的,这样,操作系<BR>统中会充斥着大量“无意义”的包。一般我们不认为这类接口为支持选播的,驱动程序<BR>不在dev-&gt;flags中置IFF_MULTICAST。<BR>点到点接口是一种特殊情况,它们通常接收所有的包,根本不进行任何硬件过滤。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;能区别选播包和其它包(主机到主机或播送)的接口。这类接口可以被要求<BR>接收所有的选播包,然后用软件来判断自己是否是有效的接收者。这种情形引入的开销<BR>是可以接收的,因为一个典型的网络中选播包的数量都很少。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;能够进行选播地址硬件检测的接口。可以给这类接口一组需要接收的选播地<BR>址,它们会忽略其它的选播包。这对核心来说是最优化的情况,因为不会浪费处理器事<BR>件去丢弃接口收到的“无意义”的包。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>核心试图利用高级接口的能力,能最好地支持第三类接口(用途最广)。因此,当有效<BR>的选播地址被改变时核心应通知驱动程序,它把新的一组地址传给驱动程序,这样它可<BR>以按照新的信息更新硬件过滤器。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>以按照新的信息更新硬件过滤器。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>核心对选播的支持<BR>&nbsp;<BR>下面是与驱动程序的选播能力相关的数据结构和函数的概括:<BR>&nbsp;<BR>void&nbsp;(*dev-&gt;set_multicast_list)(struct&nbsp;device&nbsp;*dev)<BR>&nbsp;<BR>当与设备相关的机器地址表改变时调用这个设备方法。当dev-&gt;flags被修改时它也被调<BR>用,因为有些标志也要求你重新配置硬件过滤器。这个方法接收一个指向device结构的<BR>指针作为参数,返回void。对实现这个方法不感兴趣的驱动程序可以留域为NULL。<BR>&nbsp;<BR>struct&nbsp;dev_mc_list&nbsp;*dev-&gt;mc_list<BR>&nbsp;<BR>这是域设备相关的所有选播地址的链表。这个结构的实际定义在本节结束时介绍。<BR>&nbsp;<BR>int&nbsp;dev-&gt;mc_count<BR>&nbsp;<BR>链表项数。这个信息有点冗余,但检查mc_count是否为0是优于列表检查的一个有用的快<BR>捷方式。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>IFF_MULTICAST<BR>&nbsp;<BR>除非驱动程序在dev-&gt;flags中设置了这个标志,接口将不必处理选播包。当dev-&gt;flags<BR>改变时,至少set_multicast_list会被调用。<BR>&nbsp;<BR>IFF_ALLMULTI<BR>&nbsp;<BR>dev-&gt;flags中的这个标志被网络软件设置以告诉驱动程序从网络中抽取所有播送包。这<BR>在multicast-routing被使用时发生。如果这个标志被置位,dev-&gt;mc_list将不再使用去<BR>过滤选播包。<BR>&nbsp;<BR>IFF_PROMISC<BR>&nbsp;<BR>当接口被置为杂乱模式时,dev-&gt;flags中的这个标志被设置。所有的包都被接口抽取,<BR>不考虑dev-&gt;mc_list。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>驱动程序开发者需要的最后一点信息是结构dev_mc_list的定义,它居于&lt;linux/netdevi<BR>ce.h&gt;中。<BR>&nbsp;<BR>(代码337)<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>(代码337)<BR>&nbsp;<BR>由于选播和硬件地址与包的实际发送无关,这个结构可在不同的网络实现上移植,每个<BR>地址由一串八元组和一个长度确定,就象dev-&gt;dev_addr。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>一个典型的实现<BR>&nbsp;<BR>描述set_multicast_list设计的最号办法是给出一些伪代码。<BR>&nbsp;<BR>下面的函数是这个函数在一个全特征(ff)驱动程序中的一个典型实现。说这个驱动程序<BR>是全特征的是因为它控制的接口有一个复杂的硬件包过滤器,它可以存放一个由本机接<BR>收的选播地址表。这个表的最大尺寸是FF_TABLE_SIZE。<BR>&nbsp;<BR>所由带有前缀ff_的函数是放置硬件特定操作的地方。<BR>&nbsp;<BR>(代码338)<BR>&nbsp;<BR>如果这个接口不能在硬件过滤器中存储到来包的选播表,那么这个实现还可以简化。在<BR>这种情况下,FF_TABLE_SIZE减为0,代码的最后四行也不需要了。<BR>&nbsp;<BR>现在,接口板一般不能存储选播表。不过,这并不是一个大问题,因为网络代码的高层<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>现在,接口板一般不能存储选播表。不过,这并不是一个大问题,因为网络代码的高层<BR>会负责将不需要的包丢弃。<BR>&nbsp;<BR>如我前面建议的,即使不能处理选播包的接口也需要实现set_multicast_list方法,这<BR>样当dev-&gt;flags发生改变时可以被通知。我称这个为“无特征”(nf)的实现。它非常简<BR>单,如下面所示:<BR>&nbsp;<BR>(代码339)<BR>&nbsp;<BR>处理IFF_PROMISC是很重要的,因为不然的话,用户将无法运行tcpdump或其它一些网络<BR>分析工具。另一方面,如果接口运行一个点到点的连接,则没有任何实现set_multicast<BR>_list的必要,因为它们接收所有的包。<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>快速参考<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>本节提供在本章中介绍的概念的参考。它也解释了驱动程序应包含的每个头文件的作用<BR>。不过,device和sk_buff的每个域的列表,就不再重复了。<BR>&nbsp;<BR>#include&nbsp;&lt;linux/netdevice.h&gt;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>#include&nbsp;&lt;linux/netdevice.h&gt;<BR>&nbsp;<BR>这个头文件含有struct&nbsp;device的定义,还包含了网络驱动程序需要的几个其它头文件。<BR>&nbsp;<BR>&nbsp;<BR>void&nbsp;netif_rx(struct&nbsp;sk_buff&nbsp;*skb);<BR>&nbsp;<BR>这个函数在中断时可以被调用通知核心一个包被收到了,并且封装在一个套接字缓冲区<BR>中。<BR>&nbsp;<BR>#include&nbsp;&lt;linux/if.h&gt;<BR>&nbsp;<BR>被netdevice.h包含,这个文件声明接口标志(IFF_macros)和结构ifmap,它在网络驱动<BR>程序的ioctl实现中用重要的作用。<BR>&nbsp;<BR>#include&nbsp;&lt;linux/if_ether.h&gt;<BR>&nbsp;<BR>ETH_ALEN<BR>&nbsp;<BR>ETH_P_IP<BR>&nbsp;<BR>struct&nbsp;ethhdr;<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>struct&nbsp;enet_statistics;<BR>&nbsp;<BR>被netdevice.h包含,if_ether.h定义所有的ETH_macros,用来表示八元组长度(象地址<BR>长度)和网络协议(象IP)。它也定义了结构ethhdr和enet_statistics。注意,不要看<BR>enet_statistics的名字和包含它的头文件,事实上,所有的接口都要用到它,不仅仅是<BR>以太网。<BR>&nbsp;<BR>#include&nbsp;&lt;linux/skbuff.h&gt;<BR>&nbsp;<BR>结构sk_buff和一些相关结构的定义,以及在缓冲区上操作的线入函数。这个头文件包含<BR>在netdevice.h中。<BR>&nbsp;<BR>#include&nbsp;&lt;linux/etherdevice.h&gt;<BR>&nbsp;<BR>void&nbsp;ether_setup(struct&nbsp;device&nbsp;*dev);<BR>&nbsp;<BR>这个函数为以太网驱动程序设置大多数设备方法为通用目的的实现。它同样设置dev-&gt;fl<BR>ags,并且在名字中的第一个字符是空格或空字符时,将下一个可用的ethx名赋给dev-&gt;n<BR>ame。<BR>&nbsp;<BR>unsigned&nbsp;short&nbsp;eth_type_trans(struct&nbsp;sk_buff&nbsp;*skb,&nbsp;struct&nbsp;device&nbsp;*dev)<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>unsigned&nbsp;short&nbsp;eth_type_trans(struct&nbsp;sk_buff&nbsp;*skb,&nbsp;struct&nbsp;device&nbsp;*dev)<BR>&nbsp;<BR>当以太网接口收到一个包,这个函数将被调用来设置skb-&gt;pkt_type。返回值是一个协议<BR>号,通常被存在skb-&gt;protocol中。<BR>&nbsp;<BR>#include&nbsp;&lt;linux/sockios.h&gt;<BR>SIOCDEVPRIVATE<BR>这是16个ioctl命令的第一个,可以被每个驱动程序实现以供私用。所有的网络ioctl命<BR>令都在sockios.h中定义。<BR>&nbsp;<BR>--<BR><FONT 
      color=#00ff00>※&nbsp;来源:.华南网木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;202.38.196.234]</FONT><BR>--<BR><FONT 
      color=#00ffff>※&nbsp;转寄:.华南网木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#0000ff>※&nbsp;转寄:.华南网木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#ffff00>※&nbsp;转载:.南京大学小百合站&nbsp;bbs.nju.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#ff0000>※&nbsp;转载:·饮水思源&nbsp;bbs.sjtu.edu.cn·[FROM:&nbsp;211.80.41.106]</FONT><BR></P></FONT>
      <P align=center><A href="http://joyfire.net/lsdp/index.htm"><FONT 
      color=#ffffff size=2>目录页</FONT></A> | <A 
      href="http://joyfire.net/lsdp/17.htm"><FONT color=#ffffff 
      size=2>上一页</FONT></A> | <A href="http://joyfire.net/lsdp/19.htm"><FONT 
      color=#ffffff size=2>下一页</FONT></A></P></SPAN></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>
  <TBODY>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -