一、系统框架图镇楼
二、main函数
1、参数解析
for (;;) {
c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:");
if (c < 0)
break;
switch (c) {
case 'h':
usage();
break;
case 'd':
debug++;
if (wpa_debug_level > 0)
wpa_debug_level--;
break;
case 'B':
daemonize++;
break;
case 'e':
entropy_file = optarg;
break;
case 'f':
log_file = optarg;
break;
case 'K':
wpa_debug_show_keys++;
break;
case 'P':
os_free(pid_file);
pid_file = os_rel2abs_path(optarg);
break;
case 't':
wpa_debug_timestamp++;
break;
#ifdef CONFIG_DEBUG_LINUX_TRACING
case 'T':
enable_trace_dbg = 1;
break;
#endif /* CONFIG_DEBUG_LINUX_TRACING */
case 'v':
show_version();
exit(1);
break;
case 'g':
if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
return -1;
break;
case 'G':
if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
return -1;
break;
case 'b':
tmp_bss = os_realloc_array(bss_config,
num_bss_configs + 1,
sizeof(char *));
if (tmp_bss == NULL)
goto out;
bss_config = tmp_bss;
bss_config[num_bss_configs++] = optarg;
break;
#ifdef CONFIG_DEBUG_SYSLOG
case 's':
wpa_debug_syslog = 1;
break;
#endif /* CONFIG_DEBUG_SYSLOG */
case 'S':
start_ifaces_in_sync = 1;
break;
#ifdef CONFIG_WPS
case 'u':
return gen_uuid(optarg);
#endif /* CONFIG_WPS */
case 'i':
if (hostapd_get_interface_names(&if_names,
&if_names_size, optarg))
goto out;
break;
default:
usage();
break;
}
}
关键函数getopt,是个命令行参数解析函数
一二参数与main函数的对应参数意思一样,三参是选项字符串
三参有特定的格式(a.单个字符串表示选项;b.单个字符后面跟个冒号,表示后面必须有一个参数,参数跟在选项后面或者以空格隔开;c.单个字符后面跟两个冒号,表示后面必须有一个参数,且参数必须紧跟在选项后面
参数的指针都会赋值给optarg
optind是下一个要处理选项的索引,默认是1,从第一个选项开始
extern int optind; /* index of first non-option in argv */
extern int optopt; /* single option character, as parsed */
extern int opterr; /* flag to enable built-in diagnostics... */
/* (user may set to zero, to suppress) */
extern char *optarg; /* pointer to argument of current option */
extern int getopt(int nargc, char * const *nargv, const char *options);
比如一般hostapd的启动命令是这样的,可以参照上面的代码解析一下
hostapd -P xxx/pidFile -G xxx/xxx -B xxx/xxx.conf &
至于有多少个接口,就得看后面有多少个.conf文件了
interfaces.count = argc - optind;
if (interfaces.count || num_bss_configs) {
interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
sizeof(struct hostapd_iface *));
if (interfaces.iface == NULL) {
wpa_printf(MSG_ERROR, "malloc failed");
return -1;
}
}
2、关键初始化
hostapd_global_init
eloop_init //初始化eloop全局变量
random_init
eloop_register_read_sock //eloop进入死循环监听socket
hostapd_interface_init
hostapd_init
nterfaces->config_read_cb hostapd_config_read //读取conf配置
hostapd_config_fill //填充参数
hostapd_driver_init
3、启动接口
hostapd_setup_interface
setup_interface
setup_interface2
hostapd_select_hw_mode
hostapd_check_chans //通过频段判断是固定信道,还是需要acs
hostapd_is_usable_chans
acs_init
acs_request_scan
hostapd_driver_scan
hapd->driver->scan2 //这里开始就控制驱动扫描了
acs_scan_complete //自动信道在acs回调函数中完成接口初始化
hostapd_setup_interface_complete //固定信道在这里完成接口初始化
hostapd_setup_interface_complete_sync
4、完成启动
hostapd_global_run