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