看 wpa_supplicant 的初始化,首先当然需要一份 wpa_supplicant 初始化的log啦,没log怎么一步一步学
adb logcat -c
adb logcat -s wpa_supplicant
(log很多,这里就不展示了,如果将开发者选项中 wifi verbose logging 打开会更多)
直接看 wpa_supplicant/main.c 源码
int main(int argc, char *argv[])
{
int c, i;
struct wpa_interface *ifaces, *iface;
int iface_count, exitcode = -1;
struct wpa_params params;
struct wpa_global *global;
if (os_program_init())
return -1;
os_memset(¶ms, 0, sizeof(params));
params.wpa_debug_level = MSG_INFO;
iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
if (ifaces == NULL)
return -1;
iface_count = 1;
wpa_supplicant_fd_workaround(1);
exitcode = 0;
global = wpa_supplicant_init(¶ms);
if (global == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
exitcode = -1;
goto out;
} else {
wpa_printf(MSG_INFO, "Successfully initialized wpa_supplicant");
}
if (fst_global_init()) {
wpa_printf(MSG_ERROR, "Failed to initialize FST");
exitcode = -1;
goto out;
}
for (i = 0; exitcode == 0 && i < iface_count; i++) {
struct wpa_supplicant *wpa_s;
if ((ifaces[i].confname == NULL &&
ifaces[i].ctrl_interface == NULL) ||
ifaces[i].ifname == NULL) {
if (iface_count == 1 && (params.ctrl_interface || params.dbus_ctrl_interface))
break;
usage();
exitcode = -1;
break;
}
wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
if (wpa_s == NULL) {
exitcode = -1;
break;
}
}
if (exitcode == 0)
exitcode = wpa_supplicant_run(global);
wpa_supplicant_deinit(global);
fst_global_deinit();
out:
wpa_supplicant_fd_workaround(0);
os_free(ifaces);
os_free(params.pid_file);
os_program_deinit();
return exitcode;
}
看main func之前要了解一些重要的结构体,如 wpa_interface、wpa_params、wpa_global
wpa_supplicant的几个核心步骤
调用堆栈如下(就不画时序图了,太麻烦了)
wpa_supplicant_init()
eap_register_methods();
copy wpa_params into global->params;
eloop_init();
wpa_supplicant_global_ctrl_iface_init();
wpas_global_ctrl_iface_open_sock();
eloop_register_read_sock(priv->sock, wpa_supplicant_global_ctrl_iface_retrive, global, priv);
wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
wpas_notify_supplicant_initialized();
wpas_hidl_init();
wifi_display_init();
eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, wpas_periodic, global, NULL);//10s为周期
wpas_periodic
p2p_expire_peers();
wpa_bss_flush_by_age();
ap_periodic();
wpa_supplicant_init 主要做的是 创建 global_ctrl_iface,调起 hidl 服务
值得注意的是,最后注册一个会周期性执行的方法 wpas_periodic(这个后面会回头详细看看)
调用堆栈如下
wpa_supplicant_add_iface()
wpa_supplicant_init_iface()
wpa_s->conf = wpa_config_read(wpa_s->confname, NULL); //config_file.c
config = wpa_config_alloc_empty(NULL, NULL); //read config from wpa_supplicant.conf
wpa_config_alloc_empty //config.c some default config here
wpa_config_read(wpa_s->confanother, wpa_s->conf) //read config from wpa_supplicant_overlay.conf
wpas_init_driver(wpa_s, iface)
wpa_supplicant_set_driver(wpa_s, driver)
select_driver(wpa_s, i)
global->drv_priv[i] = wpa_drivers[i]->global_init(global); //此处 driver init,即 global_init
wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname);
//实质是 driver->init2 或者 driver->init
wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param)
ifname = wpa_drv_get_ifname(wpa_s);
wpa_s->radio = radio_add_interface(wpa_s, rn); //建立wlan0和phy0的联系
wpa_supplicant_init_wpa(wpa_s)
wpa_s->wpa = wpa_sm_init(ctx); //wpa_sm 的一些配置
capa_res = wpa_drv_get_capa(wpa_s, &capa); // get capa from driver,实质是调用 get_capa
wpa_supplicant_driver_init(wpa_s)
wpas_wps_init(wpa_s)
wpas_dpp_init(wpa_s)
wpa_supplicant_init_eapol(wpa_s)
wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol);
wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s);
wpa_bss_init(wpa_s)
wpas_set_wowlan_triggers(wpa_s, &capa)
wpa_supplicant_set_default_scan_ies(wpa_s)
wpas_notify_iface_added(wpa_s)
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
nl80211_global_init //上述的 global_init
global->netlink = netlink_init(cfg);
wpa_driver_nl80211_init_nl_global(global)
//这里涉及到 netlink 的使用,没必要深究
nl80211_register_eloop_read(&global->nl_event, wpa_driver_nl80211_event_receive, global->nl_cb, 0);
eloop_register_read_sock(nl_socket_get_fd(*handle), wpa_driver_nl80211_event_receive, global->nl_cb, *handle); // 所以我们知道通过netlink报过来的事件都由 wpa_driver_nl80211_event_receive 处理
global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
wpa_driver_nl80211_init //上述的 init2
wpa_driver_nl80211_drv_init
nl80211_init_bss
wpa_driver_nl80211_finish_drv_init
wpa_driver_nl80211_capa
wpa_driver_nl80211_get_info
msg = nl80211_cmd_msg(drv->first_bss, flags, NL80211_CMD_GET_WIPHY);
send_and_recv_msgs(drv, msg, wiphy_info_handler, info, NULL, NULL)
wiphy_info_handler // 了解 driver 的能力
wpa_driver_nl80211_set_mode(bss, nlmode)
wpa_driver_nl80211_drv_init_rfkill(drv)
drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
int wpa_supplicant_run(struct wpa_global *global)
{
struct wpa_supplicant *wpa_s;
if (global->params.daemonize &&
(wpa_supplicant_daemon(global->params.pid_file) ||
eloop_sock_requeue()))
return -1;
if (global->params.wait_for_monitor) {
for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next)
if (wpa_s->ctrl_iface && !wpa_s->p2p_mgmt)
wpa_supplicant_ctrl_iface_wait(
wpa_s->ctrl_iface);
}
eloop_register_signal_terminate(wpa_supplicant_terminate, global);
eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
eloop_run(); //eloop 开跑
return 0;
}
初始化log中有很多 wifi协议和特性相关 的名词,很多尚未学习过