• 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
    
    externalwpa_supplicant_8wpa_supplicantmain.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.
    ");
    			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;
    }
    
    externalwpa_supplicant_8wpa_supplicantwpa_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
    ");
    		return NULL;
    	}
    #endif
    
    	return global;
    }
    
    externalwpa_supplicant_8srcdriversdrivers.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
    };
    
    对应驱动函数
    externalwpa_supplicant_8srcdriversdriver_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);
    	}
    }
    	
    externalwpa_supplicant_8wpa_supplicantwpa_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;
    }
    
    externalwpa_supplicant_8wpa_supplicantsrcutilseloop.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;
    }
    
  • 相关阅读:
    python 读取邮件
    windows 关于时间的计算
    python 发送 smtp
    常用HTML富文本编辑器
    数据库设计:用户登录系统数据库表设计
    在当前页面打开一个固定的窗口(页面):这种方式弹出来的窗口进行表单提交可更新父类窗口
    后台模板
    springboot/springmvc转换器
    设计模式目录
    组合条件分页查询
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/9946648.html
Copyright © 2020-2023  润新知