嵌入式Linux系统,一般都支持wifi联网,可以通过sh脚本或其它语言代码编程来实现wifi联网。
本篇来介绍一种通过sh脚本来配置wifi的脚本执行原理。
1 sh脚本wifi联网介绍
这里以飞凌开发板中的wifi启动脚本为例来介绍。
在飞凌开发板的串口中,执行如下命令(调用fltest_wifi.sh脚本,并指定一些参数),进行wifi连接:
fltest_wifi.sh -i mlan0 -s "wifi_name" -p wifi_password
- wifi_name是自己的wifi名称wifi_password是对于的wifi密码
然后ifconfig指令可以查看板子IP信息:
[root@ok3568:/usr/sbin]# ifconfig
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:239 errors:0 dropped:0 overruns:0 frame:0
TX packets:239 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:346556 (338.4 KiB) TX bytes:346556 (338.4 KiB)
mlan0 Link encap:Ethernet HWaddr E8:FB:1C:66:AF:DF
inet addr:192.168.5.111 Bcast:192.168.5.255 Mask:255.255.255.0
inet6 addr: fe80::eafb:1cff:fe66:afdf/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1799 errors:0 dropped:0 overruns:0 frame:0
TX packets:981 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:109635 (107.0 KiB) TX bytes:331552 (323.7 KiB)
[root@ok3568:/usr/sbin]#
可以看到,mlan0这个网络接口的IP为192.168.5.111
2 fltest_wifi.sh脚本文件分析
下面来具体分析fltest_wifi.sh脚本的内容。
2.1 开头部分分析
先来看开头的这段脚本:
cnt1=`ps aux | grep hostapd | grep -v grep | wc -l`
if [ "$cnt1" != "0" ];then
killall hostapd > /dev/null
fi
/etc/init.d/S80dnsmasq stop > /dev/null
分析:
首先是执行一条指令,确认正在运行的hostapd进程的个数,保存在cnt1变量中
ps aux
-
- :查看系统中当前正在运行的所有进程的详细信息
| grep hostapd | grep -v grep
-
- :匹配包含hostapd 并且不包含grep字样的行
| wc -l
- :统计行数(word count,字数统计)
注:“ps aux” 其实是一种组合使用的命令形式
hostapd的功能是用来创建AP,因为是要连接wifi,而不是创建热点,所以如果有hostapd进程,则停掉。
如果cnt1不为0,则杀掉所有的hostapd进程
killall
:用于通过进程名来终止一个或多个正在运行的进程
-
- :Linux中常用的一种重定向操作,用于将命令的输出重定向到指定的位置
/dev/null
:一个特殊的设备文件,可以接收任何写入的数据,但会直接丢弃这些数据
然后,执行/etc/init.d/S80dnsmasq stop
2.1.1 S80dnsmasq脚本分析
S80dnsmasq 也是一个脚本,内容为:
#!/bin/sh
[ -f /etc/dnsmasq.conf ] || exit 0
case "$1" in
start)
printf "Starting dnsmasq: "
start-stop-daemon -S -x /usr/sbin/dnsmasq
[ $? = 0 ] && echo "OK" || echo "FAIL"
;;
stop)
printf "Stopping dnsmasq: "
start-stop-daemon -K -q -x /usr/sbin/dnsmasq
[ $? = 0 ] && echo "OK" || echo "FAIL"
;;
restart|reload)
$0 stop
$0 start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
exit 0
先来看这一句,含义是检查指定文件dnsmasq.conf是否存在且为普通文件,若不存在,则退出
[ -f /etc/dnsmasq.conf ] || exit 0
分析:
[
-
- 和
]
-
- :这是
test
-
- 命令的一种语法糖形式(一种更简洁、方便书写的等效形式),用于条件测试。
-f
-
- :这是
test
-
- 命令的一个选项参数,用于判断指定的对象是否为普通文件
||
-
- :这是 shell 中的逻辑或运算符
exit 0
- :shell 命令,退出当前的脚本执行环境或者命令行执行环境,返回值0表示正常退出
接下来,case用来判断脚本的输入参数并进行处理,如果参数是stop,则执行:
printf "Stopping dnsmasq: "
start-stop-daemon -K -q -x /usr/sbin/dnsmasq
[ $? = 0 ] && echo "OK" || echo "FAIL"
分析:
start-stop-daemon
-
- 是一个用于管理守护进程(daemon)的工具,上述命令具体是要对
dnsmasq
-
- 这个守护进程进行某种操作。
-K
-
- :该选项通常用于向指定的守护进程发送一个信号,以实现停止(kill)该进程的目的。
-q
-
- :表示 “quiet”,即安静模式。在这种模式下,命令执行过程中不会产生太多的额外输出信息。
-x /usr/sbin/dnsmasq
-
- :其中
-x
-
- 用于指定要操作的可执行文件路径,这里明确指定了要对位于
/usr/sbin/dnsmasq
-
- 的
dnsmasq
- 可执行文件所对应的守护进程进行操作。
2.1.2 dnsmasq.conf
再来看下dnsmasq.conf 中的内容:
interface=uap0
bind-interfaces
except-interface=lo
dhcp-range=192.168.2.100,192.168.2.254,12h
dhcp-option=3,192.168.2.1
dhcp-option=6,192.168.2.1
它是dnsmasq软件的的一个配置文件
interface=uap0
:指定了要绑定或进行相关网络操作的网络接口名称为 uap0
。
bind-interfaces
:指示软件要绑定到指定的网络接口(在这里就是前面提到的 uap0
接口)。它确保了相关的网络服务(如 DHCP 服务、DNS 转发等,如果适用)只会在这个特定接口上进行操作,而不会影响到其他未指定的接口。
except-interface=lo
:lo
通常代表本地回环接口(loopback interface)。设置 except-interface=lo
表示在进行上述的绑定操作以及后续的网络服务提供过程中,要排除本地回环接口。
dhcp-range=192.168.2.100,192.168.2.254,12h
:作为 DHCP 服务器的配置项,它指定了要分配给客户端的 IP 地址范围以及租约期限。具体来说:
192.168.2.100
和192.168.2.254
:这两个 IP 地址界定了可分配给客户端的 IP 地址区间。
12h
:表示租约期限为 12 小时。
dhcp-option=3,192.168.2.1
:这是设置 DHCP 选项的配置项。在这里的3
通常代表默认网关选项(default gateway option)。
dhcp-option=6,192.168.2.1
:同样是设置 DHCP 选项的配置项。这里的 6
通常代表 DNS 服务器选项(DNS server option)。
2.2 参数解析部分
usage()和parse_args()是编写的两个函数,用于打印帮助信息和解析脚本的输入参数
function usage()
{
echo "Usage: -i <wifi> -s <ssid> -p <password>"
echo "eg: ./wifi.sh -i mlan0 -s bjforlinx -p 12345678 "
echo "eg: ./wifi.sh -i mlan0 -s bjforlinx -p NONE "
echo " -i : mlan0 or mlan1"
echo " -s : wifi ssid"
echo " -p : wifi password or NONE"
}
function parse_args()
{
while true; do
case "$1" in
-i ) wifi=$2;echo wifi $wifi;shift 2 ;;
-s ) ssid=$2;echo ssid $ssid;shift 2 ;;
-p ) pasw=$2;echo pasw $pasw;shift 2 ;;
-h ) usage; exit 1 ;;
* ) break ;;
esac
done
}
if [ $# != 6 ]
then
usage;
exit 1;
fi
parse_args $@
该脚本的功能部分是:判断fltest_wifi.sh脚本的输入参数是否为6个:
- 如果不是,则打印帮助信息,并退出如果是,则对脚本的6个输入参数进行解析
再来回顾下,6个参数:
fltest_wifi.sh -i mlan0 -s "wifi_name" -p wifi_password
2.3 连接wifi部分
连接wifi使用的是wpa_supplicant工具,wpa_supplicant全称Wi-Fi Protected Access Supplicant。
2.3.1 修改wpa_supplicant配置文件
if [ -e /etc/wpa_supplicant.conf ]
then
rm /etc/wpa_supplicant.conf
fi
echo #PSK/TKIP >> /etc/wpa_supplicant.conf
echo ctrl_interface=/var/run/wpa_supplicant >>/etc/wpa_supplicant.conf
echo ctrl_interface_group=0 >>/etc/wpa_supplicant.conf
echo update_config=1 >>/etc/wpa_supplicant.conf
echo network={ >>/etc/wpa_supplicant.conf
echo ssid="$ssid" >>/etc/wpa_supplicant.conf
echo scan_ssid=1 >>/etc/wpa_supplicant.conf
if [ $pasw == NONE ]
then
echo key_mgmt=NONE >>/etc/wpa_supplicant.conf
else
echo psk="$pasw" >>/etc/wpa_supplicant.conf
echo key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE >>/etc/wpa_supplicant.conf
echo group=CCMP TKIP WEP104 WEP40 >>/etc/wpa_supplicant.conf
fi
echo } >>/etc/wpa_supplicant.conf
我们可以看下wpa_supplicant.conf最终被修改后的内容
#PSK/TKIP
ctrl_interface=/var/run/wpa_supplicant
ctrl_interface_group=0
update_config=1
network={
ssid="MERCURY_3394"
scan_ssid=1
psk="2H2+O2=2H2O"
key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
group=CCMP TKIP WEP104 WEP40
}
2.3.2 一些ifconfig指令关闭网络接口
ifconfig -a|grep mlan0 |grep -v grep > /dev/null
if [ $? -eq 0 ]
then
ifconfig mlan0 down > /dev/null
fi
ifconfig -a|grep mlan1 |grep -v grep > /dev/null
if [ $? -eq 0 ]
then
ifconfig mlan1 down > /dev/null
fi
ifconfig -a|grep eth0 |grep -v grep > /dev/null
if [ $? -eq 0 ]
then
ifconfig eth0 down > /dev/null
fi
ifconfig -a|grep eth1 |grep -v grep > /dev/null
if [ $? -eq 0 ]
then
ifconfig eth1 down > /dev/null
fi
分析:
ifconfig -a
- :用于查看系统中所有网络接口(包括已启用和未启用的)的详细配置信息然后查找mlan0、mlan1、eth0、eth1,如果有这些网络接口,则将其关闭
2.3.3 停掉wpa_supplicant
ps -fe|grep wpa_supplicant |grep -v grep > /dev/null
if [ $? -eq 0 ]
then
kill -9 $(pidof wpa_supplicant)
fi
分析:ps -fe
是全面详细地查看系统中所有用户启动的所有进程的状态信息
-f
-
- 表示以全格式(full format)显示进程信息
-e
- 表示显示所有用户(包括其他用户和终端用户)的进程
如果存在wpa_supplicant进程在运行,则杀掉该进程
2.3.4 启用指定的网络接口
sleep 1
ifconfig $wifi up > /dev/null
sleep 1
up
-
- 是
ifconfig
-
- 命令中设置网络接口为启用状态的一个参数。
$wifi
- :是一个变量,在parse_args()中对其进行赋值,即mlan0这个网络接口。
2.3.5 通过wpa_supplicant进行配网
(wpa_supplicant -Dnl80211,wext -i$wifi -c/etc/wpa_supplicant.conf >/dev/null) &
echo "waiting..."
sleep 3
wpa_cli -i$wifi status |grep COMPLETED |grep -v grep >/dev/null
if [ $? -eq 0 ]
then
udhcpc -i $wifi
echo "Finshed!"
else
echo "try to connect again..."
sleep 3
wpa_cli -i$wifi status |grep COMPLETED |grep -v grep >/dev/null
if [ $? -eq 0 ]
then
udhcpc -i $wifi
echo "nameserver 114.114.114.114" > /etc/resolv.conf
echo "Finshed!"
else
echo "************************************************"
echo "connect faild,please check the passward and ssid"
kill -9 $(pidof wpa_supplicant)
exit 1
fi
fi
先来看第一条,该命令是在后台启动 wpa_supplicant
进程,并按照指定的参数进行无线网络配置相关的操作
(wpa_supplicant -Dnl80211,wext -i$wifi -c/etc/wpa_supplicant.conf >/dev/null) &
主要分析wpa_supplicant的参数选项:
-D
:用于指定驱动程序类型。
nl80211
和
wext
:是两种常见的无线网卡驱动程序类型。在这里同时指定这两种驱动程序类型。
-i
:用于指定要连接的无线网络接口名称。
-c
:用于指定配置文件的路径。
等待3秒后,再来看这条指令,用于检查通过指定无线网络接口连接wifi的认证过程是否已经完成:
wpa_cli -i$wifi status |grep COMPLETED |grep -v grep >/dev/null
分析:
wpa_cli
:是与wpa_supplicant
-
- 配套使用的命令行工具,用于与wpa_supplicant
-
- 进程进行交互。
-i
:用于指定要连接的无线网络接口名称。
status
:是wpa_cli
- 命令的一个操作,用于查询指定无线网络接口的连接状态信息。然后查找输出信息中是否包含COMPLETED字样
我们可以手动输入前半部分指令:
[root@ok3568:/usr/sbin]# wpa_cli -imlan0 status
bssid=f4:ee:14:1b:33:94
freq=2412
ssid=MERCURY_3394
id=0
mode=station
pairwise_cipher=CCMP
group_cipher=CCMP
key_mgmt=WPA2-PSK
wpa_state=COMPLETED
ip_address=192.168.5.111
p2p_device_address=e8:fb:1c:66:af:df
address=e8:fb:1c:66:af:df
uuid=dbddbcf1-3fcd-54be-b9aa-57858a84189f
[root@ok3568:/usr/sbin]#
可以看到,wpa_state=COMPLETED
根据查询结果,如果连接成功,则尝试获取一个动态 IP 地址。如果失败,则继续尝试连接:
if [ $? -eq 0 ]
then
udhcpc -i $wifi
echo "Finshed!"
else
echo "try to connect again..."
udhcpc
- :用于获取动态 IP 地址的客户端程序。
udhcpc
是Linux中一个常用的动态主机配置协议(DHCP)客户端程序,用于从网络中的 DHCP 服务器获取动态 IP 地址以及相关的网络配置参数。获取动态IP获取获取动态IP获取(子网掩码、动态网关、DNS服务器地址)
2.4 整体回顾
- 停掉hostapd(创建WAP无线接入点的软件)停掉dnsmasq(DNS 转发器和 DHCP 服务器软)读取解析参数(网络接口名、wifi名称、wifi密码)根据参数,修改/etc/wpa_supplicant.conf文件关闭mlan0、mlan1、eth0、eth1这些网络接口停掉wpa_supplicant启用指定的网络接口(mlan0)通过wpa_supplicant进行配网(搭配wpa_supplicant.conf文件)使用udhcpc获取一个动态 IP 地址
另外,这里再整理一些易混的名词:
AP:Access Point,无线接入点
WPA:Wi-Fi Protected Access,Wi-Fi安全的无线接入点
hostapd:是Linux系统中带加密功能的无线接入点(AP)程序
hostapd_cli:是hostapd中包含一个基于文本的使用工具
wpa_supplicant:(Wi-Fi Protected Access Supplicant)用来扫描和连接AP,后台运行
wpa_cli:用来搜索、设置和连接网络
udhcpd:工作在server端的DHCP服务,用来为设备分配IP地址
udhcpc:工作在client端的DHCP服务,用来获取IP地址
3 总结
本篇,以飞凌嵌入式Linux开发板为例,介绍了其自带的wifi配网脚本的执行原理。通过自动配置wpa_supplicant.conf文件,并调用wpa_supplicant进行wifi配网。下篇,将继续介绍如何通过C/C++编程,来实现wifi配网。