Linux wext和nl80211接口简介

Linux无线驱动接口解析
本文介绍了Linux下的两种无线驱动接口:wext和nl80211。详细讲解了它们的发展历程、技术特点及应用场景,并对比了两者的优劣。

原文地址如下,感谢您到分享!http://blog.youkuaiyun.com/dickjtk/article/details/11862815

linux无线驱动接口简介

    在分析wpa_supplicant软件linux版本下无线驱动事件和无线驱动配置代码之前,先简单介绍下linux无线驱动接口的实现技术和发展情况。

    Linux无线驱动接口有两种标准接口,wext(Wireless Extensions无线扩展接口)和nl80211接口。

    在linux-2.6.18版本之前,linux内核代码中并没有提供无线驱动接口以及无线驱动协议栈。wext是由开发者Jean Tourrilhes (惠普实验室软件工程师)定义的一套供用户层软件访问无线驱动以及驱动事件通知用户层的接口。当时无线驱动的协议栈软件比较多,如开源项目hostap,madwifi,mac80211,ieee80211协议栈以及无线芯片厂商自己实现的协议栈,基本都使用wext接口。wext接口也逐渐成为一套标准的接口。在linux-2.6.18版本,wext和mac80211协议栈并入内核,成为linux kernel的一部分。wext接口随着802.11协议从802.11,802.11b,802.11a/g的发展,,其API也不断增加,伴随着就是其wext的版本号不断变化。

    wext的接口实现上,应用层采用ioctl方式访问驱动,设置无线参数或者获取无线参数,配置无线驱动进行联网操作。无线驱动事件到应用层的传递采用的netlink socket技术,一种netlink route消息技术。这也是很多其他类型的驱动标准的实现方法。但在linux-2.6.25(记得不是很清楚了,懒得确定了)之后,wext API接口版本停止在V22就不再进行更新了。而替代其的是nl80211接口。

    nl80211接口其实在linux-2.6.18并入wext和mac80211协议栈的时候已经提供,但当时的功能还不完整,而且应用层的软件还是都使用WEXT接口,驱动基本不使用nl80211接口实现(除了基于mac80211协议栈的驱动)。 nl80211接口是由开发者Johannes Berg实现的,他也是cfg80211(无线协议栈配置接口,在无线驱动接口和mac80211之间的接口)和mac80211的维护者。无论是用户层访问驱动还是驱动事件通知应用层,nl80211接口都采用的netlink技术。

   nl80211接口逐渐替代wext接口的原因主要是使用netlink技术在应用层和内核层数据交换上相比ioctl方式具有优势,具体的比较见点击打开链接(转载的一篇文章,写得非常清楚),而且很多其他之前使用ioctl的驱动也逐渐采用了netlink方式。再一个原因就是802.11协议的发展,随着802.11n协议以及P2P,WPS无线规范的加入,协议的很多功能可以在应用层实现,增加了很多应用层与驱动层间的API接口和事件。WEXT接口不方便功能扩展的缺点,nl80211可以完全支持wext的所有功能,又可以在不修改内核的情况下增加命令字和事件。无线驱动接口从wext发展到nl80211也就顺理成章。

  目前linux内核中无线驱动的实现大部分基于mac80211协议栈,无线驱动接口也是可选的,可以使用任意一种,也可以同时使用。wpa_supplicant编译时,则根据无线驱动的接口使用情况,确定采用哪种配置接口。

  nl80211除了确定应用层和驱动层的交互标准外,对802.11协议的实现功能划分产生影响。目前通常的802.11 SME功能(无线服务管理实体,即协议栈功能)在驱动或者芯片固件中实现,nl802.11的作者希望在应用层实现更多的协议功能。wpa_supplicant(包括hostapd)除了实现WPA认证,P2P,WPS的大部分功能外,它还实现了SME功能,在这种功能划分模式下,无线驱动基本上只需要实现配置硬件和数据收发功能。

  linux系统下wpa_supplicant的Driver Event模块和Driver I/F模块(这两者实现是在一个文件,初始化在一个函数,划分成两个模块只是设计理解更清晰)的分析也分wext部分和nl80211部分。

<think>我们讨论的是wpa_supplicant如何调用nl80211接口nl80211Linux内核中用于配置无线设备的通用Netlink接口。wpa_supplicant通过nl80211驱动与内核交互,执行扫描、连接等操作。 步骤逻辑: 1. **初始化nl80211接口**:首先,wpa_supplicant在初始化时会尝试加载nl80211驱动,建立Netlink套接字,并与内核的nl80211模块通信。 2. **发送命令**:通过Netlink套接字发送nl80211命令(如NL80211_CMD_TRIGGER_SCAN触发扫描,NL80211_CMD_CONNECT发起连接等)。 3. **接收事件**:通过同一套接字监听来自内核的事件(如扫描完成、认证事件等)。 关键代码示例(以扫描为例): 在`driver_nl80211.c`中,扫描请求函数`wpa_driver_nl80211_scan`会构造一个NL80211_CMD_TRIGGER_SCAN类型的Netlink消息,并发送给内核。 ```c static int wpa_driver_nl80211_scan(void *priv, struct wpa_driver_scan_params *params) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; int ret; // 分配Netlink消息 msg = nlmsg_alloc(); if (!msg) return -ENOMEM; // 构造消息:指定命令类型(触发扫描)接口索引 genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, NL80211_CMD_TRIGGER_SCAN, 0); NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); // 添加扫描参数(可选,如SSID列表等) // ... 省略参数设置代码 ... // 发送消息 ret = send_and_recv_msgs(drv, msg, NULL, NULL); if (ret == 0) { // 扫描请求已成功发送 drv->scan_for_auth = 0; } return ret; nla_put_failure: nlmsg_free(msg); return -ENOBUFS; } ``` 调用流程: 1. 上层(如状态机)调用`wpa_driver_scan`函数,该函数会调用驱动注册的扫描操作(即`drv->scan2`指向的函数,在nl80211中就是`wpa_driver_nl80211_scan`)。 2. 在`wpa_driver_nl80211_scan`中构造Netlink消息并发送。 3. 内核执行扫描,完成后通过Netlink发送事件(NL80211_CMD_NEW_SCAN_RESULTS)。 4. wpa_supplicant在事件循环中接收该事件,并处理扫描结果。 事件处理: 在`nl80211_event_receive`函数中,会处理来自内核的Netlink消息,根据消息类型(如NL80211_CMD_NEW_SCAN_RESULTS)调用相应的事件处理函数。 ```c static void nl80211_event_receive(struct nl_msg *msg, void *arg) { struct nlattr *tb[NL80211_ATTR_MAX + 1]; struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); struct wpa_driver_nl80211_data *drv = arg; // 解析属性 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); // 根据消息类型处理 switch (gnlh->cmd) { case NL80211_CMD_NEW_SCAN_RESULTS: // 处理扫描结果 wpa_driver_nl80211_event_scan_results(drv); break; // ... 其他事件处理 ... } } ``` 总结:wpa_supplicant通过Netlink套接字与内核的nl80211接口通信,发送命令并接收事件。 §§相关问题§§ 1. 在发送nl80211命令时,如何确保消息格式符合内核期望? 2. 当多个无线接口存在时,nl80211如何区分不同接口的事件? 3. 如何处理nl80211命令执行失败的情况(例如返回错误码)? 4. nl80211接口支持哪些主要的Wi-Fi操作(除了扫描连接)? 5. 为什么nl80211比旧的wext接口更受欢迎? </think>### 回答用户问题:wpa_supplicant调用nl80211接口的实现机制 wpa_supplicant通过**Netlink Socket**与Linux内核的nl80211接口通信,核心流程如下: #### 调用架构 ```mermaid graph TB W[wpa_supplicant] -->|netlink socket| N[nl80211] N -->|ioctl/sysfs| K[内核WiFi堆栈] K -->|事件通知| W ``` #### 关键实现步骤 1. **nl80211驱动初始化** 在`driver_nl80211.c`中建立netlink连接: ```c int wpa_driver_nl80211_init(void) { // 创建netlink socket drv->nl_sock = nl_socket_alloc(); // 连接nl80211家族 genl_connect(drv->nl_sock); // 解析nl80211家族ID drv->nl80211_id = genl_ctrl_resolve(drv->nl_sock, "nl80211"); } ``` 2. **命令发送机制** 构造并发送nl80211命令(以扫描为例): ```c static int nl80211_scan(struct wpa_driver_nl80211_data *drv) { // 创建netlink消息 struct nl_msg *msg = nlmsg_alloc(); // 填充命令头 genlmsg_put(msg, 0, 0, drv->nl80211_id, 0, NLM_F_DUMP, NL80211_CMD_TRIGGER_SCAN, 0); // 添加接口索引参数 nla_put_u32(msg, NL80211_ATTR_IFINDEX, drv->ifindex); // 发送到内核 nl_send_auto(drv->nl_sock, msg); nlmsg_free(msg); } ``` 3. **事件接收处理** 注册消息接收回调: ```c void nl80211_event_receive(int sock, void *eloop_ctx, void *sock_ctx) { struct nl_msg *msg = nlmsg_alloc(); // 接收内核消息 nl_recvmsgs(drv->nl_sock, &nl_cb); // 解析事件类型 genlmsg_parse(nlmsg_hdr(msg), 0, tb, NL80211_ATTR_MAX, NULL); // 根据事件类型分发处理 switch (gnlh->cmd) { case NL80211_CMD_NEW_SCAN_RESULTS: process_scan_results(drv); break; case NL80211_CMD_CONNECT: handle_connect_event(drv); break; } } ``` #### 典型调用场景 1. **WiFi扫描** 命令序列: `NL80211_CMD_TRIGGER_SCAN` → `NL80211_CMD_NEW_SCAN_RESULTS` 2. **连接AP** 关键参数结构: ```c struct nl80211_connect_params { u8 *bssid; // AP MAC地址 u8 *ssid; // 网络SSID size_t ssid_len; // SSID长度 int freq; // 连接频率 }; ``` 调用命令:`NL80211_CMD_CONNECT` 3. **断开连接** 命令:`NL80211_CMD_DISCONNECT` #### 错误处理机制 ```c int res = nl_send_auto(drv->nl_sock, msg); if (res < 0) { wpa_printf(MSG_ERROR, "nl80211: Send failed: %d", res); // 自动重试机制 if (drv->retry_count++ < MAX_RETRY) eloop_register_timeout(0, 100000, retry_cb, drv, NULL); } ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值