zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Maven 环境的配置
    zTree的简单例子
    plsql免安装客户端的配置
    HDU 1232 畅通工程
    HDU 5698 瞬间移动
    Codeforces 1015E1 Stars Drawing (Easy Edition)
    Codeforces 784B Santa Claus and Keyboard Check
    Codeforces 500C New Year Book Reading
    NSarray 赋值 拷贝 等问题记录
    UINavigationController 操作记录
  • 原文地址:https://www.cnblogs.com/helloworldtoyou/p/9946648.html
Copyright © 2011-2022 走看看