嵌入式Linux系統(tǒng),一般都支持wifi聯網,可以通過sh腳本或其它語言代碼編程來實現wifi聯網。
本篇來介紹一種通過sh腳本來配置wifi的腳本執(zhí)行原理。
1 sh腳本wifi聯網介紹
這里以飛凌開發(fā)板中的wifi啟動腳本為例來介紹。
在飛凌開發(fā)板的串口中,執(zhí)行如下命令(調用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
分析:
首先是執(zhí)行一條指令,確認正在運行的hostapd進程的個數,保存在cnt1變量中
ps aux
-
- :查看系統(tǒng)中當前正在運行的所有進程的詳細信息
| grep hostapd | grep -v grep
-
- :匹配包含hostapd 并且不包含grep字樣的行
| wc -l
- :統(tǒng)計行數(word count,字數統(tǒng)計)
注:“ps aux” 其實是一種組合使用的命令形式
“ps” 是 “process status”(進程狀態(tài))的縮寫“a” 表示顯示所有用戶(包括其他用戶和終端用戶)的進程,不僅僅是當前用戶啟動的進程“u” 表示以用戶為導向的詳細格式(user-oriented detailed format)來顯示進程信息,會給出諸如啟動進程的用戶、進程占用的 CPU 和內存資源百分比、進程狀態(tài)等更為詳細的信息“x” 表示顯示沒有控制終端的進程,也就是那些在后臺運行的、不是通過常規(guī)終端啟動的進程
hostapd
是Linux中一款用于創(chuàng)建無線接入點(Wireless Access Point,WAP)的軟件
hostapd的功能是用來創(chuàng)建AP,因為是要連接wifi,而不是創(chuàng)建熱點,所以如果有hostapd進程,則停掉。
如果cnt1不為0,則殺掉所有的hostapd進程
killall
:用于通過進程名來終止一個或多個正在運行的進程
-
- :Linux中常用的一種重定向操作,用于將命令的輸出重定向到指定的位置
/dev/null
:一個特殊的設備文件,可以接收任何寫入的數據,但會直接丟棄這些數據
然后,執(zhí)行/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 命令,退出當前的腳本執(zhí)行環(huán)境或者命令行執(zhí)行環(huán)境,返回值0表示正常退出
接下來,case用來判斷腳本的輸入參數并進行處理,如果參數是stop,則執(zhí)行:
printf "Stopping dnsmasq: "
start-stop-daemon -K -q -x /usr/sbin/dnsmasq
[ $? = 0 ] && echo "OK" || echo "FAIL"
分析:
start-stop-daemon
-
- 是一個用于管理守護進程(daemon)的工具,上述命令具體是要對
dnsmasq
-
- 這個守護進程進行某種操作。
-K
-
- :該選項通常用于向指定的守護進程發(fā)送一個信號,以實現停止(kill)該進程的目的。
-q
-
- :表示 “quiet”,即安靜模式。在這種模式下,命令執(zhí)行過程中不會產生太多的額外輸出信息。
-x /usr/sbin/dnsmasq
-
- :其中
-x
-
- 用于指定要操作的可執(zhí)行文件路徑,這里明確指定了要對位于
/usr/sbin/dnsmasq
-
- 的
dnsmasq
- 可執(zhí)行文件所對應的守護進程進行操作。
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 轉發(fā)等,如果適用)只會在這個特定接口上進行操作,而不會影響到其他未指定的接口。
except-interface=lo
:lo
通常代表本地回環(huán)接口(loopback interface)。設置 except-interface=lo
表示在進行上述的綁定操作以及后續(xù)的網絡服務提供過程中,要排除本地回環(huán)接口。
dhcp-range=192.168.2.100,192.168.2.254,12h
:作為 DHCP 服務器的配置項,它指定了要分配給客戶端的 IP 地址范圍以及租約期限。具體來說:
192.168.2.100
和192.168.2.254
:這兩個 IP 地址界定了可分配給客戶端的 IP 地址區(qū)間。
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
- :用于查看系統(tǒng)中所有網絡接口(包括已啟用和未啟用的)的詳細配置信息然后查找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
是全面詳細地查看系統(tǒng)中所有用戶啟動的所有進程的狀態(tài)信息
-f
-
- 表示以全格式(full format)顯示進程信息
-e
- 表示顯示所有用戶(包括其他用戶和終端用戶)的進程
如果存在wpa_supplicant進程在運行,則殺掉該進程
2.3.4 啟用指定的網絡接口
sleep 1
ifconfig $wifi up > /dev/null
sleep 1
up
-
- 是
ifconfig
-
- 命令中設置網絡接口為啟用狀態(tài)的一個參數。
$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
- 命令的一個操作,用于查詢指定無線網絡接口的連接狀態(tài)信息。然后查找輸出信息中是否包含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
根據查詢結果,如果連接成功,則嘗試獲取一個動態(tài) IP 地址。如果失敗,則繼續(xù)嘗試連接:
if [ $? -eq 0 ]
then
udhcpc -i $wifi
echo "Finshed!"
else
echo "try to connect again..."
udhcpc
- :用于獲取動態(tài) IP 地址的客戶端程序。
udhcpc
是Linux中一個常用的動態(tài)主機配置協(xié)議(DHCP)客戶端程序,用于從網絡中的 DHCP 服務器獲取動態(tài) IP 地址以及相關的網絡配置參數。獲取動態(tài)IP獲取獲取動態(tài)IP獲?。?a class="article-link" target="_blank" href="/baike/1568921.html">子網掩碼、動態(tài)網關、DNS服務器地址)
2.4 整體回顧
- 停掉hostapd(創(chuàng)建WAP無線接入點的軟件)停掉dnsmasq(DNS 轉發(fā)器和 DHCP 服務器軟)讀取解析參數(網絡接口名、wifi名稱、wifi密碼)根據參數,修改/etc/wpa_supplicant.conf文件關閉mlan0、mlan1、eth0、eth1這些網絡接口停掉wpa_supplicant啟用指定的網絡接口(mlan0)通過wpa_supplicant進行配網(搭配wpa_supplicant.conf文件)使用udhcpc獲取一個動態(tài) IP 地址
另外,這里再整理一些易混的名詞:
AP:Access Point,無線接入點
WPA:Wi-Fi Protected Access,Wi-Fi安全的無線接入點
hostapd:是Linux系統(tǒng)中帶加密功能的無線接入點(AP)程序
hostapd_cli:是hostapd中包含一個基于文本的使用工具
wpa_supplicant:(Wi-Fi Protected Access Supplicant)用來掃描和連接AP,后臺運行
wpa_cli:用來搜索、設置和連接網絡
udhcpd:工作在server端的DHCP服務,用來為設備分配IP地址
udhcpc:工作在client端的DHCP服務,用來獲取IP地址
3 總結
本篇,以飛凌嵌入式Linux開發(fā)板為例,介紹了其自帶的wifi配網腳本的執(zhí)行原理。通過自動配置wpa_supplicant.conf文件,并調用wpa_supplicant進行wifi配網。下篇,將繼續(xù)介紹如何通過C/C++編程,來實現wifi配網。