Android wpa_supplicant 启动过程

记录wpa_supplicant启动过程

ini脚本:
service wpa_supplicant /vendor/bin/hw/wpa_supplicant \
    -ip2p0 -Dnl80211 -c/data/misc/wifi/p2p_supplicant.conf \
    -I/vendor/etc/wifi/p2p_supplicant_overlay.conf -N \ 
    -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
    -I/vendor/etc/wifi/wpa_supplicant_overlay.conf \
    -O/data/misc/wifi/sockets -puse_p2p_group_interface=1 -dd \
    -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
#   we will start as root and wpa_supplicant will switch to user wifi 
#   after setting up the capabilities required for WEXT 
#   user wifi 
#   group wifi inet keystore
    class main 
    socket wpa_wlan0 dgram 660 wifi wifi 
    disabled
    oneshot

external\wpa_supplicant_8\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(&params, 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);

    for (;;) {
        c = getopt(argc, argv,
               "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsS:TtuvW");
        if (c < 0)
            break;
        switch (c) {
        case 'b':
            iface->bridge_ifname = optarg;
            break;
        case 'B':
            params.daemonize++;
            break;
        case 'c':       // 配置文件 /data/misc/wifi/wpa_supplicant.conf
            iface->confname = optarg;
            break;
        case 'C':
            iface->ctrl_interface = optarg;
            break;
        case 'D':       // 驱动 nl80211
            iface->driver = optarg;
            break;
        case 'd':
#ifdef CONFIG_NO_STDOUT_DEBUG
            printf("Debugging disabled with "
                   "CONFIG_NO_STDOUT_DEBUG=y build time "
                   "option.\n");
            goto out;
#else /* CONFIG_NO_STDOUT_DEBUG */
            params.wpa_debug_level--;
            break;
#endif /* CONFIG_NO_STDOUT_DEBUG */
        case 'e':       // 加密文件 /data/misc/wifi/entropy.bin
            params.entropy_file = optarg;
            break;
#ifdef CONFIG_DEBUG_FILE
        case 'f':
            params.wpa_debug_file_path = optarg;
            break;
#endif /* CONFIG_DEBUG_FILE */
        case 'g':   // 接口 @android:wpa_wlan0
            params.ctrl_interface = optarg;
            break;
        case 'G':
            params.ctrl_interface_group = optarg;
            break;
        case 'h':
            usage();
            exitcode = 0;
            goto out;
        case 'i':   // 接口名称 wlan0
            iface->ifname = optarg;
            break;
            ......
        default:
            usage();
            exitcode = 0;
            goto out;
        }
    }

    exitcode = 0;
    global = wpa_supplicant_init(&params);          //
    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;
    }

#if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
    if (!fst_global_add_ctrl(fst_ctrl_cli))
        wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
#endif

    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 ||
#ifdef CONFIG_MATCH_IFACE
                         params.match_iface_count ||
#endif /* CONFIG_MATCH_IFACE */
                         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;
        }
    }

#ifdef CONFIG_MATCH_IFACE
    if (exitcode == 0)
        exitcode = wpa_supplicant_init_match(global);
#endif /* CONFIG_MATCH_IFACE */

    if (exitcode == 0)
        exitcode = wpa_supplicant_run(global);              // 启动eloop,监听wpa的事件

    wpa_supplicant_deinit(global);

    fst_global_deinit();

out:
    wpa_supplicant_fd_workaround(0);
    os_free(ifaces);
#ifdef CONFIG_MATCH_IFACE
    os_free(params.match_ifaces);
#endif /* CONFIG_MATCH_IFACE */
    os_free(params.pid_file);

    os_program_deinit();

    return exitcode;
}

external\wpa_supplicant_8\wpa_supplicant\wpa_supplicant.c
struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
{
    struct wpa_global *global;
    int ret, i;

    if (params == NULL)
        return NULL;

#ifdef CONFIG_DRIVER_NDIS
    {
        void driver_ndis_init_ops(void);
        driver_ndis_init_ops();
    }
#endif /* CONFIG_DRIVER_NDIS */

#ifndef CONFIG_NO_WPA_MSG
    wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
#endif /* CONFIG_NO_WPA_MSG */
    // 如果没有设置debug文件,将日志写道stdout
    if (params->wpa_debug_file_path)
        wpa_debug_open_file(params->wpa_debug_file_path);
    else
        wpa_debug_setup_stdout();
    if (params->wpa_debug_syslog)
        wpa_debug_open_syslog();
    if (params->wpa_debug_tracing) {
        ret = wpa_debug_open_linux_tracing();
        if (ret) {
            wpa_printf(MSG_ERROR,
                   "Failed to enable trace logging");
            return NULL;
        }
    }
    // 注册eap方法,是一个链表,将支持的eap方法添加到链表中
    ret = eap_register_methods();   // 注册eap方法
    if (ret) {
        wpa_printf(MSG_ERROR, "Failed to register EAP methods");
        if (ret == -2)
            wpa_printf(MSG_ERROR, "Two or more EAP methods used "
                   "the same EAP type.");
        return NULL;
    }

    global = os_zalloc(sizeof(*global));
    if (global == NULL)
        return NULL;
    dl_list_init(&global->p2p_srv_bonjour);
    dl_list_init(&global->p2p_srv_upnp);
    /// 将启动参数添加到global->params中
    global->params.daemonize = params->daemonize;
    global->params.wait_for_monitor = params->wait_for_monitor;
    global->params.dbus_ctrl_interface = params->dbus_ctrl_interface;
    if (params->pid_file)
        global->params.pid_file = os_strdup(params->pid_file);
    if (params->ctrl_interface)
        global->params.ctrl_interface =
            os_strdup(params->ctrl_interface);
    if (params->ctrl_interface_group)
        global->params.ctrl_interface_group =
            os_strdup(params->ctrl_interface_group);
    if (params->override_driver)
        global->params.override_driver =
            os_strdup(params->override_driver);
    if (params->override_ctrl_interface)
        global->params.override_ctrl_interface =
            os_strdup(params->override_ctrl_interface);
#ifdef CONFIG_MATCH_IFACE
    global->params.match_iface_count = params->match_iface_count;
    if (params->match_iface_count) {
        global->params.match_ifaces =
            os_calloc(params->match_iface_count,
                  sizeof(struct wpa_interface));
        os_memcpy(global->params.match_ifaces,
              params->match_ifaces,
              params->match_iface_count *
              sizeof(struct wpa_interface));
    }
#endif /* CONFIG_MATCH_IFACE */
#ifdef CONFIG_P2P
    if (params->conf_p2p_dev)
        global->params.conf_p2p_dev =
            os_strdup(params->conf_p2p_dev);
#endif /* CONFIG_P2P */
    wpa_debug_level = global->params.wpa_debug_level =
        params->wpa_debug_level;
    wpa_debug_show_keys = global->params.wpa_debug_show_keys =
        params->wpa_debug_show_keys;
    wpa_debug_timestamp = global->params.wpa_debug_timestamp =
        params->wpa_debug_timestamp;
#ifdef CONFIG_HIDL
    if (params->hidl_service_name)
        global->params.hidl_service_name =
            os_strdup(params->hidl_service_name);
#endif /* CONFIG_HIDL */

    wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR);

    if (eloop_init()) {
        wpa_printf(MSG_ERROR, "Failed to initialize event loop");
        wpa_supplicant_deinit(global);
        return NULL;
    }
    // 随机数
    random_init(params->entropy_file);

    global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
    if (global->ctrl_iface == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }

    if (wpas_notify_supplicant_initialized(global)) {
        wpa_supplicant_deinit(global);
        return NULL;
    }
    // wpa_drivers记录了不同接口的操作方法。
    for (i = 0; wpa_drivers[i]; i++)
        global->drv_count++;
    if (global->drv_count == 0) {
        wpa_printf(MSG_ERROR, "No drivers enabled");
        wpa_supplicant_deinit(global);
        return NULL;
    }
    global->drv_priv = os_zalloc(global->drv_count * sizeof(void *));
    if (global->drv_priv == NULL) {
        wpa_supplicant_deinit(global);
        return NULL;
    }

#ifdef CONFIG_WIFI_DISPLAY
    if (wifi_display_init(global) < 0) {
        wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display");
        wpa_supplicant_deinit(global);
        return NULL;
    }
#endif /* CONFIG_WIFI_DISPLAY */

    eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
                   wpas_periodic, global, NULL);

#ifdef CONFIG_WAPI
    if (wapi_asue_init()) {
        wpa_printf(MSG_ERROR, "wapi: wapi_asue_init fail\n");
        return NULL;
    }
#endif

    return global;
}

external\wpa_supplicant_8\src\drivers\drivers.c
const struct wpa_driver_ops *const wpa_drivers[] =
{
#ifdef CONFIG_DRIVER_NL80211
    &wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
#ifdef CONFIG_DRIVER_WEXT
    &wpa_driver_wext_ops,
#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_HOSTAP
    &wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_BSD
    &wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */
#ifdef CONFIG_DRIVER_OPENBSD
    &wpa_driver_openbsd_ops,
#endif /* CONFIG_DRIVER_OPENBSD */
#ifdef CONFIG_DRIVER_NDIS
    &wpa_driver_ndis_ops,
#endif /* CONFIG_DRIVER_NDIS */
#ifdef CONFIG_DRIVER_WIRED
    &wpa_driver_wired_ops,
#endif /* CONFIG_DRIVER_WIRED */
#ifdef CONFIG_DRIVER_MACSEC_LINUX
    &wpa_driver_macsec_linux_ops,
#endif /* CONFIG_DRIVER_MACSEC_LINUX */
#ifdef CONFIG_DRIVER_MACSEC_QCA
    &wpa_driver_macsec_qca_ops,
#endif /* CONFIG_DRIVER_MACSEC_QCA */
#ifdef CONFIG_DRIVER_ROBOSWITCH
    &wpa_driver_roboswitch_ops,
#endif /* CONFIG_DRIVER_ROBOSWITCH */
#ifdef CONFIG_DRIVER_ATHEROS
    &wpa_driver_atheros_ops,
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_NONE
    &wpa_driver_none_ops,
#endif /* CONFIG_DRIVER_NONE */
    NULL
};

对应驱动函数
external\wpa_supplicant_8\src\drivers\driver_nl80211.c
const struct wpa_driver_ops wpa_driver_nl80211_ops = {
    .name = "nl80211",
    .desc = "Linux nl80211/cfg80211",
    .get_bssid = wpa_driver_nl80211_get_bssid,
    .get_ssid = wpa_driver_nl80211_get_ssid,
    .set_key = driver_nl80211_set_key,
    .scan2 = driver_nl80211_scan2,
    .sched_scan = wpa_driver_nl80211_sched_scan,
    .stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
    .get_scan_results2 = wpa_driver_nl80211_get_scan_results,
    .abort_scan = wpa_driver_nl80211_abort_scan,
    .deauthenticate = driver_nl80211_deauthenticate,
    .authenticate = driver_nl80211_authenticate,
    .associate = wpa_driver_nl80211_associate,
    .global_init = nl80211_global_init,
    .global_deinit = nl80211_global_deinit,
    .init2 = wpa_driver_nl80211_init,
    .deinit = driver_nl80211_deinit,
    .get_capa = wpa_driver_nl80211_get_capa,
    .set_operstate = wpa_driver_nl80211_set_operstate,
    .set_supp_port = wpa_driver_nl80211_set_supp_port,
    .set_country = wpa_driver_nl80211_set_country,
    .get_country = wpa_driver_nl80211_get_country,
    .set_ap = wpa_driver_nl80211_set_ap,
    .set_acl = wpa_driver_nl80211_set_acl,
    .if_add = wpa_driver_nl80211_if_add,
    .if_remove = driver_nl80211_if_remove,
    .send_mlme = driver_nl80211_send_mlme,
    .get_hw_feature_data = nl80211_get_hw_feature_data,
    .sta_add = wpa_driver_nl80211_sta_add,
    .sta_remove = driver_nl80211_sta_remove,
    .hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
    .sta_set_flags = wpa_driver_nl80211_sta_set_flags,
    .hapd_init = i802_init,
    .hapd_deinit = i802_deinit,
    .set_wds_sta = i802_set_wds_sta,
    .get_seqnum = i802_get_seqnum,
    .flush = i802_flush,
    .get_inact_sec = i802_get_inact_sec,
    .sta_clear_stats = i802_sta_clear_stats,
    .set_rts = i802_set_rts,
    .set_frag = i802_set_frag,
    .set_tx_queue_params = i802_set_tx_queue_params,
    .set_sta_vlan = driver_nl80211_set_sta_vlan,
    .sta_deauth = i802_sta_deauth,
    .sta_disassoc = i802_sta_disassoc,
    .read_sta_data = driver_nl80211_read_sta_data,
    .set_freq = i802_set_freq,
    .send_action = driver_nl80211_send_action,
    .send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
    .remain_on_channel = wpa_driver_nl80211_remain_on_channel,
    .cancel_remain_on_channel =
    wpa_driver_nl80211_cancel_remain_on_channel,
    .probe_req_report = driver_nl80211_probe_req_report,
    .deinit_ap = wpa_driver_nl80211_deinit_ap,
    .deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
    .resume = wpa_driver_nl80211_resume,
    .signal_monitor = nl80211_signal_monitor,
...}

struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global,
                         struct wpa_interface *iface,
                         struct wpa_supplicant *parent)
{
    struct wpa_supplicant *wpa_s;
    struct wpa_interface t_iface;
    struct wpa_ssid *ssid;

    if (global == NULL || iface == NULL)
        return NULL;

    wpa_s = wpa_supplicant_alloc(parent);
    if (wpa_s == NULL)
        return NULL;

    wpa_s->global = global;

    t_iface = *iface;
    if (global->params.override_driver) {
        wpa_printf(MSG_DEBUG, "Override interface parameter: driver "
               "('%s' -> '%s')",
               iface->driver, global->params.override_driver);
        t_iface.driver = global->params.override_driver;
    }
    if (global->params.override_ctrl_interface) {
        wpa_printf(MSG_DEBUG, "Override interface parameter: "
               "ctrl_interface ('%s' -> '%s')",
               iface->ctrl_interface,
               global->params.override_ctrl_interface);
        t_iface.ctrl_interface =
            global->params.override_ctrl_interface;
    }
    if (wpa_supplicant_init_iface(wpa_s, &t_iface)) {
        wpa_printf(MSG_DEBUG, "Failed to add interface %s",
               iface->ifname);
        wpa_supplicant_deinit_iface(wpa_s, 0, 0);
        return NULL;
    }

    /* Notify the control interfaces about new iface */
    if (wpas_notify_iface_added(wpa_s)) {
        wpa_supplicant_deinit_iface(wpa_s, 1, 0);
        return NULL;
    }

    /* Notify the control interfaces about new networks for non p2p mgmt
     * ifaces. */
    if (iface->p2p_mgmt == 0) {
        for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next)
            wpas_notify_network_added(wpa_s, ssid);
    }

    wpa_s->next = global->ifaces;
    global->ifaces = wpa_s;

    wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname);
    wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);

#ifdef CONFIG_P2P
    if (wpa_s->global->p2p == NULL &&
        !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled &&
        (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
        wpas_p2p_add_p2pdev_interface(
            wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) {
        wpa_printf(MSG_INFO,
               "P2P: Failed to enable P2P Device interface");
        /* Try to continue without. P2P will be disabled. */
    }
#endif /* CONFIG_P2P */

    return wpa_s;
}


static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s,
                     struct wpa_interface *iface)
{
    struct wpa_driver_capa capa;
    int capa_res;
    u8 dfs_domain;

    wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver "
           "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname,
           iface->confname ? iface->confname : "N/A",
           iface->driver ? iface->driver : "default",
           iface->ctrl_interface ? iface->ctrl_interface : "N/A",
           iface->bridge_ifname ? iface->bridge_ifname : "N/A");

    if (iface->confname) {
#ifdef CONFIG_BACKEND_FILE
        wpa_s->confname = os_rel2abs_path(iface->confname);
        if (wpa_s->confname == NULL) {
            wpa_printf(MSG_ERROR, "Failed to get absolute path "
                   "for configuration file '%s'.",
                   iface->confname);
            return -1;
        }
        wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'",
               iface->confname, wpa_s->confname);
#else /* CONFIG_BACKEND_FILE */
        wpa_s->confname = os_strdup(iface->confname);
#endif /* CONFIG_BACKEND_FILE */
        // 读取conf文件
        wpa_s->conf = wpa_config_read(wpa_s->confname, NULL);
        if (wpa_s->conf == NULL) {
            wpa_printf(MSG_ERROR, "Failed to read or parse "
                   "configuration '%s'.", wpa_s->confname);
            return -1;
        }
        // 为什么还有一个文件
        wpa_s->confanother = os_rel2abs_path(iface->confanother);
        wpa_config_read(wpa_s->confanother, wpa_s->conf);
    }
}
    
external\wpa_supplicant_8\wpa_supplicant\wpa_supplicant.c
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;

#ifdef CONFIG_MATCH_IFACE
    if (wpa_supplicant_match_existing(global))
        return -1;
#endif

    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();

    return 0;
}

external\wpa_supplicant_8\wpa_supplicant\src\utils\eloop.c
void eloop_run(void)
{
#ifdef CONFIG_ELOOP_POLL
    int num_poll_fds;
    int timeout_ms = 0;
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
    fd_set *rfds, *wfds, *efds;
    struct timeval _tv;
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
    int timeout_ms = -1;
#endif /* CONFIG_ELOOP_EPOLL */
#ifdef CONFIG_ELOOP_KQUEUE
    struct timespec ts;
#endif /* CONFIG_ELOOP_KQUEUE */
    int res;
    struct os_reltime tv, now;

#ifdef CONFIG_ELOOP_SELECT
    rfds = os_malloc(sizeof(*rfds));
    wfds = os_malloc(sizeof(*wfds));
    efds = os_malloc(sizeof(*efds));
    if (rfds == NULL || wfds == NULL || efds == NULL)
        goto out;
#endif /* CONFIG_ELOOP_SELECT */

    while (!eloop.terminate &&
           (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 ||
        eloop.writers.count > 0 || eloop.exceptions.count > 0)) {
        struct eloop_timeout *timeout;

        if (eloop.pending_terminate) {
            /*
             * This may happen in some corner cases where a signal
             * is received during a blocking operation. We need to
             * process the pending signals and exit if requested to
             * avoid hitting the SIGALRM limit if the blocking
             * operation took more than two seconds.
             */
            eloop_process_pending_signals();
            if (eloop.terminate)
                break;
        }

        timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
                    list);
        if (timeout) {
            os_get_reltime(&now);
            if (os_reltime_before(&now, &timeout->time))
                os_reltime_sub(&timeout->time, &now, &tv);
            else
                tv.sec = tv.usec = 0;
#if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
            timeout_ms = tv.sec * 1000 + tv.usec / 1000;
#endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
#ifdef CONFIG_ELOOP_SELECT
            _tv.tv_sec = tv.sec;
            _tv.tv_usec = tv.usec;
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_KQUEUE
            ts.tv_sec = tv.sec;
            ts.tv_nsec = tv.usec * 1000L;
#endif /* CONFIG_ELOOP_KQUEUE */
        }

#ifdef CONFIG_ELOOP_POLL
        // 将事件添加到监听队列里面
        num_poll_fds = eloop_sock_table_set_fds(
            &eloop.readers, &eloop.writers, &eloop.exceptions,
            eloop.pollfds, eloop.pollfds_map,
            eloop.max_pollfd_map);
        // 监听事件变化
        res = poll(eloop.pollfds, num_poll_fds,
               timeout ? timeout_ms : -1);
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
        // 将事件添加到监听队列里面
        eloop_sock_table_set_fds(&eloop.readers, rfds);
        eloop_sock_table_set_fds(&eloop.writers, wfds);
        eloop_sock_table_set_fds(&eloop.exceptions, efds);
        // 监听事件变化
        res = select(eloop.max_sock + 1, rfds, wfds, efds,
                 timeout ? &_tv : NULL);
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
        if (eloop.count == 0) {
            res = 0;
        } else {
            res = epoll_wait(eloop.epollfd, eloop.epoll_events,
                     eloop.count, timeout_ms);
        }
#endif /* CONFIG_ELOOP_EPOLL */
#ifdef CONFIG_ELOOP_KQUEUE
        if (eloop.count == 0) {
            res = 0;
        } else {
            res = kevent(eloop.kqueuefd, NULL, 0,
                     eloop.kqueue_events, eloop.kqueue_nevents,
                     timeout ? &ts : NULL);
        }
#endif /* CONFIG_ELOOP_KQUEUE */
        if (res < 0 && errno != EINTR && errno != 0) {
            wpa_printf(MSG_ERROR, "eloop: %s: %s",
#ifdef CONFIG_ELOOP_POLL
                   "poll"
#endif /* CONFIG_ELOOP_POLL */
#ifdef CONFIG_ELOOP_SELECT
                   "select"
#endif /* CONFIG_ELOOP_SELECT */
#ifdef CONFIG_ELOOP_EPOLL
                   "epoll"
#endif /* CONFIG_ELOOP_EPOLL */
#ifdef CONFIG_ELOOP_KQUEUE
                   "kqueue"
#endif /* CONFIG_ELOOP_EKQUEUE */

                   , strerror(errno));
            goto out;
        }

        eloop.readers.changed = 0;
        eloop.writers.changed = 0;
        eloop.exceptions.changed = 0;

        eloop_process_pending_signals();

......

    }

    eloop.terminate = 0;
out:
#ifdef CONFIG_ELOOP_SELECT
    os_free(rfds);
    os_free(wfds);
    os_free(efds);
#endif /* CONFIG_ELOOP_SELECT */
    return;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值