加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
    • 1 sh脚本wifi联网介绍
    • 2 fltest_wifi.sh脚本文件分析
    • 3 总结
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

嵌入式Linux之wifi配网脚本分析

12/02 16:08
578
阅读需 28 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

嵌入式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” 其实是一种组合使用的命令形式

    “ps” 是 “process status”(进程状态)的缩写“a” 表示显示所有用户(包括其他用户和终端用户)的进程,不仅仅是当前用户启动的进程“u” 表示以用户为导向的详细格式(user-oriented detailed format)来显示进程信息,会给出诸如启动进程的用户、进程占用的 CPU 和内存资源百分比、进程状态等更为详细的信息“x” 表示显示没有控制终端的进程,也就是那些在后台运行的、不是通过常规终端启动的进程

hostapd 是Linux中一款用于创建无线接入点(Wireless Access Point,WAP)的软件

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

    可执行文件所对应的守护进程进行操作。

dnsmasq 是Linux中一款轻量级 DNS 转发器和 DHCP 服务器软件。

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=lolo 通常代表本地回环接口(loopback interface)。设置 except-interface=lo 表示在进行上述的绑定操作以及后续的网络服务提供过程中,要排除本地回环接口。

dhcp-range=192.168.2.100,192.168.2.254,12h :作为 DHCP 服务器的配置项,它指定了要分配给客户端的 IP 地址范围以及租约期限。具体来说:

192.168.2.100192.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配网。

飞凌嵌入式

飞凌嵌入式

保定飞凌嵌入式技术有限公司,创建于2006年,是一家专注嵌入式核心控制系统研发、设计和生产的高新技术企业,是国内较早专业从事嵌入式技术的企业之一。 经过十几年的发展与积累,公司拥有业内优秀的软硬件研发团队,在北京及保定建立两大研发基地,在苏州、深圳设有华东、华南技术服务中心,并在北美、欧洲以及亚太等其他国家和地区拥有国际业务网络。公司研发的智能设备核心平台广泛应用于物联网、工控、轨道交通、医疗、电力、商业电子、智能家居、安防、机器人、环境监测等诸多领域。

保定飞凌嵌入式技术有限公司,创建于2006年,是一家专注嵌入式核心控制系统研发、设计和生产的高新技术企业,是国内较早专业从事嵌入式技术的企业之一。 经过十几年的发展与积累,公司拥有业内优秀的软硬件研发团队,在北京及保定建立两大研发基地,在苏州、深圳设有华东、华南技术服务中心,并在北美、欧洲以及亚太等其他国家和地区拥有国际业务网络。公司研发的智能设备核心平台广泛应用于物联网、工控、轨道交通、医疗、电力、商业电子、智能家居、安防、机器人、环境监测等诸多领域。收起

查看更多

相关推荐

电子产业图谱

控制科学与工程硕士,日常分享单片机、嵌入式、C/C++、Linux等学习经验干货~