【wpa_supplicant】入门 && eloop 机制

居家办公快要两个月了,这段时间都没有怎么学习,感到十分懊悔
今天开始收拾心情,重新出发,重新学习

现在我意识到之前的学习路线有些问题,对很多一知半解的东西没有深挖
接受了师傅的建议,再结合自身情况,决定先把supplicant看完,然后入手driver
这个专栏会尽可能地详细解读wpa_supplicant

话不多说,开始吧

wpa_supplicant代码目录

咱是个务实的人,干啥都从代码开始搞起, talk is cheap, show me the code
android/external/wpa_supplicant_8
这是 wpa_supplicant_8 源码目录,目录下包含四个子文件夹(下段文字是摘抄自wifi学习知识点整理):

  • hostapd :hostapd能够使得无线网卡切换为master模式,模拟AP(通常可以认为是路由器)功能,也就是我们说的软AP(Soft AP)。Hostapd的功能就是作为AP的认证服务器,负责控制管理stations(通常可以认为带无线网卡的PC)的接入和认证。
  • hs20 :Hotspot 2.0(HS 2.0)由WiFi联盟和无线宽带联盟开发,旨在实现移动网络和WiFi网络之间的无缝流量切换,它不需要额外的用户注册和验证。其实Hotspot 2.0只是802.11u标准中的一个子项功能——即利用802.11u提供无缝的自动WiFi身份识别和切换,这一个新兴的协议将可帮用户省去了连接到WiFi网络和服务的麻烦和乏味的过程。Hotspot 2.0的出现,意味着我们将可以自动由3G、4G切换到WiFi网络,用户将不用手动发现热点、输入身份验证来获得WiFi。而且从一个网络切换到另一个网络的时候都不会间断, 用户甚至感觉不到。这种无缝认证和交接以及空中传送的安全性,将使得WiFi有如蜂窝网络那般易于使用,并提供一致的用户体验与新增加的WiFi网络速度上的优势,你根本感受不到自己某刻正在连接的是WiFi还是3G网络。
  • wpa_supplicant:是Android用户空间中无线网络部分的核心模块, 所有Framework层中和Wi-Fi相关的操作最终都将借由wpa_supplicant来完成
  • src :包含了一些通用的数据结构和处理方法.其他三个目录均有可能使用到

注意,hostapd/src和wpa_supplicant/src子目录均链接到此src目录(所以你修改了src路径下的文件后会发现hostapd和wpa_supplicant下的跟着改了)

wpa_supplicant简介
  • wpa_supplicant是一个开源项目,已经被移植到Linux,Windows以及很多嵌入式系统上。它是WPA的应用层认证客户端,负责完成认证相关的登录、加密等工作。
  • wpa_supplicant是一个独立运行的守护进程,其核心是一个事件驱动模块,在各种事件到来后处理WPA状态机、控制命令、驱动事件、配置信息等。
  • 经过编译后 的 wpa_supplicant源程序可以看到两个主要的可执行工具:wpa_supplicant 和 wpa_cli。wpa_supplicant是核心程序,它和wpa_cli的关系就是服务和客户端的关系:后台运行wpa_supplicant,使用wpa_cli来搜索、设置、和连接网络。(这是很早的说法,现在已经不是这样了,具体是怎样,我还不会表述,QAQ)
上手event loop

wpa_supplicant所有工作都围绕 事件 展开。即,它是基于事件驱动的。事件驱动和消息驱动类似,主线程运行一个 event loop,等待事件的发生并处理它们。WPAS没有使用多线程编程,所有事件处理都在主线程中完成。

根据之前半知半解时期的学习经验来看,最先要弄懂的就是这个 eloop 机制

下面部分内容摘自链接: wpa_supplicant之eloop_run分析
阅读以下内容前请先(至少)看完 eloop.c 前面的主要结构体

以下是eloop_data具体内容
eloop_data

这个变量会处理三大类型的Event事件:Socket事件Timeout事件Signal事件
根据eloop_data结构体分析事件的处理:

Socket事件:有 readers,writers,exceptions 三个 eloop_sock_table 结构体
每个里面都有一个 eloop_sock 类型的指针table,这里可以将该指针变量理解成动态数组
可以向各个table里面添加、删除 eloop_sock
事件分发就是遍历 eloop_sock_table,依次运行里面的每个handler

Timeout事件:每个 struct eloop_timeout 都被放在一个双向链表中
链表头就是 eloop_data 中的“timeout”项。这些struct eloop_timeout按超时先后排序

Signal事件:每个 struct eloop_signal 都通过 eloop_signal 类型的指针链接起来

eloop_run

先看eloop_run源码

void eloop_run(void)
{
   
   
	fd_set *rfds, *wfds, *efds;
	struct timeval _tv;
	int res;
	struct os_reltime tv, now;

	rfds = os_malloc(sizeof(*rfds));
	wfds = os_malloc(sizeof(*wfds));
	efds = os_malloc(sizeof(*efds));
	if (rfds == NULL
<think>我们分析用户提供的代码片段:这是wpa_supplicant_run函数的实现。用户指出“这里没有状态机”,我们需要解释状态机在何处以及为何在此函数中不明显。 首先,明确wpa_supplicant_run函数的作用:它是wpa_supplicant的主事件循环。在这个函数中,主要完成了以下工作: 1. 守护进程化(如果需要) 2. 匹配现有接口(如果配置了CONFIG_MATCH_IFACE) 3. 等待控制接口(如果配置了wait_for_monitor) 4. 注册信号处理函数(终止和重新配置) 5. 进入事件循环(eloop_run) 状态机在哪里? - wpa_supplicant的状态机并不直接在这个函数中体现,而是在事件循环(eloop_run)中被驱动。 - 状态机逻辑分散在多个回调函数中,这些回调函数通过事件循环机制被触发。 具体解析: 1. 事件循环(eloop_run)是wpa_supplicant的核心,它会不断处理各种事件(如socket事件、定时器事件、信号事件等)。 2. 当有事件发生时,预先注册的回调函数会被调用,这些回调函数中包含了状态机处理逻辑。 3. 例如,在初始化过程中,会注册驱动事件回调、控制接口命令回调等。当这些事件发生时,相应的回调函数会处理状态转换。 状态机触发点举例: - 在wpa_supplicant初始化时,通常会设置初始状态(如WPA_DISCONNECTED),然后可能触发扫描(scan)事件。 - 当扫描结果返回时,会触发扫描完成事件,进而调用`wpa_supplicant_event_scan_results`函数,该函数会根据扫描结果尝试连接网络,此时状态机会根据连接过程的状态(如AUTHENTICATING、ASSOCIATING等)进行转换。 因此,虽然wpa_supplicant_run函数中没有直接看到状态机转换的代码,但它通过事件循环驱动了整个状态机的工作流程。 回答重点: - 状态机由事件循环驱动,分散在回调函数中。 - 这个函数是主循环,负责启动事件处理,但不包含具体的状态处理逻辑。 根据要求,最后必须提出3-5个相关问题。 </think>### 回答用户问题:wpa_supplicant_run函数与状态机的关系解析 在提供的`wpa_supplicant_run()`函数代码中确实没有直接显示状态机逻辑,这是由wpa_supplicant的**事件驱动架构**决定的: #### 状态机的实际实现位置 1. **状态机核心入口** 真正的状态机位于`wpa_supplicant_event()`函数中(在`wpa_supplicant.c`): ```c void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { struct wpa_supplicant *wpa_s = ctx; // 状态机决策核心 switch (wpa_s->wpa_state) { case WPA_DISCONNECTED: handle_disconnected_state(wpa_s, event, data); break; case WPA_SCANNING: handle_scanning_state(wpa_s, event, data); break; // ...其他状态处理 } } ``` 2. **状态机驱动机制** `wpa_supplicant_run()`中的`eloop_run()`是**状态机的引擎**: ```mermaid graph LR A[eloop_run] --> B[等待事件] B -->|驱动事件| C[调用注册的回调] C --> D[wpa_supplicant_event] D --> E[状态机处理] ``` #### 为什么run函数不包含状态机 1. **关注点分离原则** - `run()`专注于**事件循环管理** - 状态机实现在**事件处理器**中 - 符合UNIX守护进程设计惯例 2. **模块化设计** ```c // 状态机注册到事件系统 void wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s) { // 注册驱动事件回调 driver_ops->event_receive = wpa_supplicant_event; } ``` 3. **状态变量位置** 状态保存在`struct wpa_supplicant`中: ```c struct wpa_supplicant { enum wpa_states wpa_state; // 当前状态 enum wpa_states new_connection; // 目标状态 // ... }; ``` #### 状态迁移触发点 状态变化发生在事件处理中: 1. 驱动事件(如`EVENT_CONNECT`) 2. 定时器事件(如扫描超时) 3. 控制接口命令(如`wpa_cli reconnect`) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值