无线技术,例如 WLAN (Wireless Local Area Network)、Bluetooth、GPRS (General Packet Radio Service)、GSM (Global System for Mobile communications) 以及 IrDa (Infrared Data),在不同的环境下提供服务。虽然 WLAN 支持比 Bluetooth 更高的速度和更长的传播距离,但是它也需要更多的费用并且耗电量更大。GPRS 虽然比 Bluetooth 和 WLAN 慢,但是可用于移动技术。尽管它们存在差异,或者是其他原因,但是具有多种无线功能的设备可以综合利用它们。例如,根据 GPS 模块的定位输入,设备可以透明地将网络连接从路上的 GPRS 切换到网吧中更便宜的 WLAN。移动电话可以通过 Bluetooth 与心律监视器通信,当病人心律超出某个极限时,就可以通过 GSM 向医生发送警报。
目前,无线技术已经以 PCMCIA、Compact Flash (CF) 卡的形式广泛应用,或者用于 USB 设备。大多数计算机系统,包括嵌入式设备,都有 PCMCIA、CF 或者 USB接口,即使不含对无线技术的内置支持,也能够立刻使用这些技术。这篇文章分析了无线设备的一些示例,并且研究了设备驱动程序的 Linux 实现、总线技术以及各种协议。
首先,通过跟踪 WLAN 样卡的代码流,您将了解到 WLAN 设备是如何在 Linux下工作的。
注意:本文涉及到的内核数据结构和文件名是当前 Linux 版本中所使用的。文件名相对于 Linux 内核源程序树的根。
Linux 802.11 WLAN
WLAN 通信系统作为有线 LAN 以外的另一种选择一般用在同一座建筑内。WLAN 使用 ISM (Industrial、Scientific、Medical) 无线电广播频段通信。WLAN 的 802.11a 标准使用 5 GHz 频段,支持的最大速度为 54 Mbps,而 802.11b 和 802.11g 标准使用 2.4 GHz 频段,分别支持最大 11 Mbps 和 54 Mbps 的速度。
WLAN 类似于有线以太网,它们都是从同一地址池分配 MAC (Media Access Control) 地址,并且都是作为以太网设备出现在操作系统的网络设备层。例如,ARP(Address Resolution Protocol) 表是用 WLAN MAC 地址和以太网 MAC 地址填充的。
然而 WLAN 与有线以太网在链路层有很大的区别。例如,802.11 标准使用冲突避免(CSMA/CA)代替有线以太网的冲突检测(CSMA/CD)。而且,与以太网帧不同的是,WLAN 帧是被确认的。
由于 WLAN 工作站之间的模糊边界,WLAN 链路层拥有在传送前清除一个区域的协议。出于安全性考虑,WLAN 的 Wired Equivalent Privacy (WEP) 加密机制提供与有线网络相同的安全级别。WEP 将 40 比特或 104 比特密钥与随机的 24 比特初始向量组合用以加解密数据。WLAN 支持两种通信模式:Ad Hoc 模式 用于小群组工作站之间不必使用访问点的短时间内通信,而 Infrastructure 模式 的所有通信必须通过访问点。访问点周期性地广播一个服务集标识符(SSID),SSID 用于将一个 WLAN 网络与其他网络区别开来。
大多数可用的 WLAN 卡是基于 Intersil Prism 或 Lucent Hermes 芯片组的。Compaq、Nokia、Linksys 和 D-Link 卡使用 Prism 芯片组,而 Lucent Orinoco 卡和 Apple Airport 使用 Hermes 芯片组。
Linux WLAN 支持
Linux WLAN 支持由 WLAN API 实现和 WLAN 设备驱动程序组成。我将依次研究它们。
有两个 Linux 项目定义一般的 WLAN API,并且提供工具让用户空间应用程序配置参数和存取来自 WLAN 设备驱动程序的信息。Wireless Extensions 项目为不同的无线网卡提供公共的 Linux 用户空间接口。这个项目的工具包括 iwconfig 用以配置参数(比如 WLAN 驱动程序中的 WEP 关键字及 SSID)。linux-wlan 项目作为 Wireless Extensions 项目一部分,也支持一系列用于从用户空间与 WLAN 设备驱动程序交互的工具。与基于 Wireless Extensions 的工具不同,这些工具使用类似于 SNMP (Simple Network Management Protocol) MIB (Management Information Base) 的语法,该语法反映 IEEE 802.11 规范。(请参阅 参考资料,获得项目的更多信息。)
继续讨论设备驱动程序,支持流行的 WLAN 卡的 Linux 设备驱动程序包括:
Orinoco WLAN 驱动程序:是 Linux 内核源代码的一部分,支持基于 Hermes 的卡和基于 Intersil Prism 的卡。orinoco_cs 模块提供了 PCMCIA 和 CF 卡所必需的 PCMCIA 卡服务支持。
linux-wlan 项目的 linux-wlan-ng 驱动程序:支持多种基于 Prism 芯片组的卡。这个驱动程序支持 linux-wlan API 并部分支持 Wireless Extensions。
Host AP 设备驱动程序:支持 Prism 芯片组的 AP 模式,可以使 WLAN 主机起访问点的作用。
Linux Symbol Spectrum 设备驱动程序:支持 Symbol PCMCIA 卡。不同于 PCMCIA 卡,Symbol CF 卡缺乏板载固件,它依靠设备驱动程序来下载固件。该驱动程序的一个单独版本适用于 CF 卡。Intel 将 Symbol PCMCIA 卡重新打包为 Intel PRO/Wireless 卡,而 Socket 通信重新打包了 Symbol CF 卡。
Atmel USB WLAN 驱动程序:利用 Atmel 芯片组支持许多 USB WLAN 设备。
Intersil Prism2 WLAN CF 卡
我将讨论 Intersil Prism2 802.11b WLAN CF 卡来展示它如何与 Linux PCMCIA、网络设备及协议层一起工作。
Linux PCMCIA/CF 层由 PCMCIA 主机控制器的设备驱动程序、不同卡的客户机驱动程序、用户模式程序、有助于热拔的后台进程和与以上各部分交互并为它们提供服务的内核卡服务中枢组成(请参阅 参考资料)。PCMCIA 控制器将卡连接到系统总线,将卡内存映射到主机 I/O 和内存窗口,并将卡产生的中断路由到自由处理器中断线。CF 卡较小,但与 PCMCIA 兼容,并且经常应用于手持设备。PCMCIA/CF 卡拥有两个存储空间:属性内存(attribute memory)和 公共内存(common memory)。属性内存类似于 Card Information Structure (CIS),用来保存配置注册和描述符信息。Linux 卡服务核心与主机控制器设备驱动程序、卡设备驱动程序及用户模式 cardmgr 后台进程交互。它在一些事件(比如卡插入、卡移出以及低电量)发生时调用卡驱动程序的事件处理程序例程。尽管卡服务从卡的 CIS 向上传送信息到 cardmgr,但是 cardmgr 将为分配内存窗口和中断级别而在用户空间(/etc/pcmcia/config.opts)中定义的资源分配策略向下传送到卡服务。查看 drivers/pcmcia/ds.c 可以了解与 cardmgr 交互的内核代码,查阅 /etc/pcmcia/config.opts 可以了解用户空间资源分配策略。
插入 Intersil WLAN CF 卡时,卡服务调用 orinoco_cs 模块的 PCMCIA 事件处理程序。卡服务解析卡属性内存中的 CIS 元组(tuples)并向上传送信息到 cardmgr,这将从 /etc/pcmcia/config 文件(参阅清单 1)加载适当的设备驱动程序。由于卡的 CIS 中的 manfid 元组匹配 /etc/pcmcia/config 中的条目,所以 cardmgr 绑定带有 orinoco_cs 驱动程序的卡。清单 1 中的设备条目规定 orinoco_cs 驱动程序由三个内核模块组成:orinoco、orinoco_cs 和 hermes。此外,由于设备属于无线的(wireless)一类,所以当启动和停止设备时,cardmgr 执行脚本 /etc/wireless/wireless。这个脚本使用 WLAN 工具和实用程序来配置设备驱动程序参数,例如 WEP 关键字和 SSID。它还可以启动 WLAN 上的网络协议,例如 DHCP(Dynamic Host Configuration Protocol,动态主机配置通讯协议)。清单 1 中的示例使用 Wireless Extensions 工具来执行设备配置。
注意: PCMCIA 配置文件的确切位置取决于所用的 Linux 分布。
清单 1. Intersil WLAN CF 卡的 PCMCIA 设备条目
card "Intersil PRISM2 11 Mbps Wireless Adapter"
manfid 0x0156, 0x0002
bind "orinoco_cs"
device "orinoco_cs"
class "wireless" module "orinoco","orinoco_cs","hermes"
用 /etc/pcmcia/wireless 和 /etc/pcmcia/wireless.opts 脚本来配置 WEP 关键字和 SSID 这样的参数。
清单 2. 配置 WLAN 特定参数
iwconfig ethX essid <wlan_name>
key AAAA-AAAA-AA [1] key BBBB-BBBB-BB [2] key CCCC-CCCC-CC [3] key DDDD-DDDD-DD [4]
: Set 64-bit WEP Keys and ESSID in the driver
iwconfig ethX : Display WLAN parameters
iwpriv : Get nongeneric, driver-specific parameters
iwlist : List Information and statistics from an interface
iwspy : Read quality of link for a set of addresses
/proc/net/wireless : Wireless Statistics from the device driver
在插入卡时,orinoco_cs 像传统的网络设备驱动程序一样,调用 register_netdev 来获得分配给 WLAN 接口的 ethX 网络接口名。它还会注册一个中断服务例程的地址以服务收发无线数据时产生的中断。中断处理程序是 orinoco 模块的一部分,并与 Linux 网络栈交互。Linux 网络栈使用主要的数据结构是 sk_buff 结构(定义在 include/linux/skbuff.h 中,请参阅 参考资料,该文件包括关于附加在它上的一个内存块的控制信息)。sk_buffs 为所有网络层提供有效的缓冲器处理和流控制机制。网络设备驱动程序执行一个 dev_alloc_skb 和一个 skb_put,以用 IP 数据填充一个 sk_buff,然后通过调用 netif_rx 将这个sk_buff 传送到 TCP/IP 栈。orinoco 中断服务例程用从 WLAN 接收的数据填充 sk_buffs,并经由 netif_rx 将它传送到 IP 栈。
Linux TCP/IP 应用程序可以在前面谈到的内核模块为 Intersil WLAN CF 卡提供的网络接口上不加更改地运行。