记录在RV1126上配置AP6212 WiFi热点模式遇到的那些“坑”

一、 前言与目标

最近在折腾手里的这块 RV1126 + AP6212 的开发板,想用它搭一个WiFi热点,方便其他设备能快速接入进行调试。本以为这是个很简单的任务,准备用Linux下最经典的组合 hostapddnsmasq 来实现。结果没想到,从最开始的配置文件,到最后的启动顺序,一路上踩了一连串的坑。

这里把整个调试过程记录下来,希望能给后来遇到同样问题的朋友们一些参考。

二、 调试之旅:我的“踩坑”与“填坑”记录
第一坑:配置文件里的“幽灵空格”与端口冲突

一开始,我满怀信心地写好了三个核心文件:hostapd.conf, dnsmasq.conf 和启动脚本 wifi_apmode.sh。结果第一次运行脚本就直接罢工了,报了两个莫名其妙的错:

  • 一个是dnsmasqAddress already in use (地址已被占用)。

  • 另一个是hostapdinvalid driver (无效驱动)。

查了半天,第一个问题是 dnsmasq.conf 里我自己画蛇添足地加了一行 port=111,想指定端口,结果和系统其他服务冲突了。把它删掉dnsmasq 就不报这个错了。

第二个 hostapd 的问题就更坑了,我逐字对比配置,最后才发现是driver=nl80211hw_mode=g 这两行的值后面,不小心多敲了一个空格!对于配置文件来说,这自然就成了不认识的非法值。把这两个“幽灵空格”删掉后,服务总算能启动了。

第二坑:热点能连,但就是不给IP

解决了初级错误后,新问题来了。我的手机和电脑都能搜到 alientek_softap 这个热点,也能输入密码连接上,但就是一直卡在“正在获取IP地址...”,最后宣告失败。

这一下就把问题锁定在了 dnsmasq 身上。既然WiFi能连上,说明hostapd已经把链路层的工作干好了,问题肯定出在DHCP分配IP的环节。

我回头仔细检查我的 wifi_apmode.sh 启动脚本,才发现犯了个致命的逻辑错误:

# 错误的顺序
dnsmasq -C dnsmasq.conf      # 我先启动了DHCP服务
ifconfig wlan0 192.168.4.3   # 然后才给网卡配IP

这怎么行呢?DHCP服务员(dnsmasq)自己都不知道餐厅(wlan0接口)的地址,怎么给客人(手机)安排座位(分配IP)?

正确的逻辑应该是先让接口拥有IP地址,再启动依赖于这个接口的服务。把这两行命令的顺序换过来,这个问题就解决了。

第三坑:时灵时不灵的IP分配,需要更“霸道”的配置

虽然调整顺序后能获取到IP了,但我发现有时候连接还是会慢,或者不稳定。我猜想是不是因为我的板子上还有一个 eth0 网口,dnsmasq 被搞糊涂了,不知道到底该听谁的。

为了让它老实点,我决定把它的配置写死,不给它任何“自由发挥”的空间。我修改了 dnsmasq.conf,增加了三个关键选项:

  • bind-interfaces: 强制它只在我指定的接口上工作。

  • listen-address=192.168.4.3: 强制它只在这个IP地址上提供服务。

  • dhcp-authoritative: 告诉所有客户端,我才是这里的老大,唯一的DHCP服务器。

最后的收尾:两个意想不到的小冲突

本以为万事大吉,结果运行优化后的配置,又冒出两个新错误:dnsmasq127.0.0.1地址冲突,hostapd 说我没设密码。

这两个问题也很好解决:

  1. Dnsmasq冲突:是因为它默认还想当DNS服务器,监听了127.0.0.1的53端口,和系统其他服务撞车了。在dnsmasq.conf里加上 port=0,把它DNS的功能彻底禁用,只做纯粹的DHCP服务,问题解决。

  2. Hostapd没密码:是我在之前优化hostapd.conf的加密方式时,追求安全(只用WPA2),结果不小心把 wpa_passphrase=... 这一行给删了。把它加回去就好了。

三、 总结与最终配置

经过这么一番折腾,总算是把这个AP功能搞定了。从最初的语法错误,到核心的逻辑顺序问题,再到服务冲突和配置细节,每一步都是一次宝贵的经验积累。下面贴出最终能在我这块 RV1126 + AP6212 板子上完美工作的配置,给有需要的朋友们“抄个作业”。

[root@ATK-DLRV1126:/wifiAP]# cat dnsmasq.conf 
# 强制dnsmasq只绑定在下面指定的接口上,不再监听其他接口(如eth0)
bind-interfaces

# 只在我们指定的wlan0接口上工作
interface=wlan0

# 监听的IP地址,必须和wlan0的静态IP一致
listen-address=192.168.4.3

# DHCP地址池
dhcp-range=192.168.4.2,192.168.4.254,255.255.255.0,24h

# 声明自己是此网段唯一的、权威的DHCP服务器,可以加快客户端获取IP的速度
dhcp-authoritative
port=0



[root@ATK-DLRV1126:/wifiAP]# cat hostapd.conf 
interface=wlan0
ssid=alientek_softap
driver=nl80211
channel=6
hw_mode=g
ignore_broadcast_ssid=0
auth_algs=1
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_passphrase=12345678
rsn_pairwise=CCMP



[root@ATK-DLRV1126:/wifiAP]# cat wifi_apmode.sh 
#!/bin/sh

echo 0 > /sys/class/rfkill/rfkill1/state
sleep 2
echo 1 > /sys/class/rfkill/rfkill1/state
sleep 2

if [[ "$(pidof dnsmasq)" != "" ]]
then
    kill -9 $(pidof dnsmasq)
fi

if [[ "$(pidof hostapd)" != "" ]]
then
    kill -9 $(pidof hostapd)
fi

connmanctl disable wifi
rfkill unblock all
ifconfig wlan0 down
sleep 1
ifconfig wlan0 up
sleep 1

# --- 以下是修改过的部分 ---
# 1. 先为wlan0接口配置静态IP地址
ifconfig wlan0 192.168.4.3
echo "wlan0 IP address set to 192.168.4.3"

# 2. 再启动dnsmasq,它现在知道要在哪个网段上提供DHCP服务了
dnsmasq -C dnsmasq.conf
echo "Dnsmasq service started"

# 3. 最后启动hostapd,创建WiFi热点
hostapd hostapd.conf -B
echo "Hostapd service started"



[root@ATK-DLRV1126:/wifiAP]# ./wifi_apmode.sh 
Disabled wifi
wlan0 IP address set to 192.168.4.3
Dnsmasq service started
Configuration file: hostapd.conf
Using interface wlan0 with hwaddr 9c:b8:b4:0d:54:44 and ssid "alientek_softap"
wlan0: interface state UNINITIALIZED->ENABLED
wlan0: AP-ENABLED 
Hostapd service started
[root@ATK-DLRV1126:/wifiAP]# 

四、 最终一步:设置开机自启动,让热点“自动化”

热点虽然能通过手动运行脚本来启动了,但这还不够,总不能每次开机都SSH上去手动敲一遍命令吧?所以,我们这趟旅程的最后一站,就是把它加入到系统的开机自启动流程里,实现真正的“自动化AP”。

1. 分析系统启动方式

要设置自启动,得先看看我这个Buildroot构建的Linux系统用的是什么启动管理器。我 ls /etc/init.d/ 了一下,看到了满屏的 S 开头的脚本(比如S45connman, S50dropbear),这很明显是老派但稳定可靠的 System V init 系统。

那就好办了,我们只需要写一个自己的启动脚本,再把它放到这个目录里就行。

2. 文件归档:给配置文件安个家

我的 hostapd.conf, dnsmasq.confwifi_apmode.sh 现在还扔在一个临时目录里,这不清真。为了方便管理和后续维护,我决定把它们统一放到一个永久的位置。

首先,我创建了一个专门的目录:

mkdir -p /usr/bin/wifiAP

然后,把三个文件都移进去:

mv wifi_apmode.sh hostapd.conf dnsmasq.conf /usr/bin/wifiAP/
3. 编写init.d启动脚本

第一次尝试:标准的 init.d 脚本

接下来就是重头戏:编写 init.d 启动脚本。我在 /etc/init.d/ 目录下新建了一个名为 S60wifi_ap 的文件。

  • 命名考量S 代表Start(启动),60 是一个启动优先级。我看了一下,系统里网络服务(S40network, S45connman)的优先级大概在40-45,我选60是为了确保它在网络相关的底层服务之后运行,保证 wlan0 接口等硬件已经准备就绪。

我在 S60wifi_ap 文件里写入了以下内容,这是一个很标准的 init.d 脚本模板,可以处理 start, stop, restart 等参数:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          wifi_ap
# Required-Start:    $network $local_fs
# Required-Stop:     $network $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start WiFi AP mode using hostapd and dnsmasq
### END INIT INFO

# AP脚本和配置文件的存放路径
AP_PATH="/usr/local/bin/wifiAP"
AP_SCRIPT="wifi_apmode.sh"

case "$1" in
  start)
    echo "Starting WiFi AP mode..."
    # 调用我们原来的主脚本来启动服务
    # 使用 sh 命令执行,并确保在正确的目录下运行
    (cd $AP_PATH && sh ./$AP_SCRIPT)
    ;;
  stop)
    echo "Stopping WiFi AP mode..."
    # 停止服务最简单的方法就是杀掉进程
    killall hostapd > /dev/null 2>&1
    killall dnsmasq > /dev/null 2>&1
    # 可以选择性地关闭wlan0接口
    ifconfig wlan0 down
    ;;
  restart)
    $0 stop
    sleep 2
    $0 start
    ;;
  *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
    ;;
esac

exit 0

注意:我在start命令里加了(cd $AP_PATH && ...),这是一个好习惯,可以确保脚本总是在正确的目录下寻找配置文件。)

将新建的/etc/init.d/S60wifi_ap加上执行权限,然后 然后我信心满满的重启开发板,等待AP自己启动,可是没能达到我的预期效果,试了几次也不行,看来还有问题,那就继续排查吧。。。

第二次尝试:日志与时序竞争
  • 问题现象:手动执行 /etc/init.d/S60wifi_ap start 完美成功,但开机就是不启动。

  • 调试思路:这明显是遇到了嵌入式开发中最经典的“时序竞争”或“环境差异”问题。开机时脚本的运行环境和时机,与我手动执行时大不相同。为了搞清楚开机时到底发生了什么,我修改了 S60wifi_ap 脚本,在开头加上了日志记录功能 exec > /tmp/wifi_ap_boot.log 2>&1,并增加了一个 sleep 10 的延时,想看看日志里会说些什么。

  • 修改后的S60wifi_ap脚本内容如下

  • #!/bin/sh
    
    # AP脚本和配置文件的存放路径
    AP_PATH="/usr/bin/wifiAP"
    AP_SCRIPT="wifi_apmode.sh"
    LOG_FILE="/tmp/wifi_ap_boot.log"
    
    # 将所有输出重定向到日志文件,方便调试
    exec > $LOG_FILE 2>&1
    
    case "$1" in
      start)
        echo "------ Starting WiFi AP at $(date) ------"
    
        # 关键步骤:等待5-10秒,给WiFi硬件和驱动充分的初始化时间
        echo "Waiting for WiFi hardware to settle..."
        sleep 10
    
        echo "Executing AP script..."
        # 先切换到AP_PATH目录,然后再执行脚本
        (cd ${AP_PATH} && sh ./${AP_SCRIPT})
    
        echo "------ WiFi AP script finished ------"
        ;;
      stop)
        echo "------ Stopping WiFi AP at $(date) ------"
        killall hostapd > /dev/null 2>&1
        killall dnsmasq > /dev/null 2>&1
        ifconfig wlan0 down
        ;;
      restart)
        $0 stop
        sleep 2
        $0 start
        ;;
      *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
        ;;
    esac
    
    exit 0
  • 关键发现:再次重启后,我登录系统,准备查看日志,结果 cat /tmp/wifi_ap_boot.log 提示 No such file or directory

这个发现是整个调试过程的最关键突破口。日志文件根本没有被创建,这无可辩驳地证明了:系统在开机过程中,压根就没运行我的 S60wifi_ap 脚本! 问题不是我的脚本执行失败了,而是它被完全忽略了。

最终的解决方案:简单粗暴,但有效

既然系统不“自动发现”并执行我的脚本,那我就只能用更直接的方法了。我怀疑在这个精简的系统中,init 进程可能只执行了一个核心的 rcS 脚本。

我的最终解决方案是:放弃调用外部脚本,将核心命令直接写入系统的主启动脚本 /etc/init.d/rcS 中。

  1. 我用vi打开了 /etc/init.d/rcS 文件。

  2. 在文件的最末尾(在 done 循环之后),我添加了以下几行代码:

     
    # ------------------- FINAL ATTEMPT: Direct WiFi AP Startup -------------------
    # This is the final attempt to start the AP service directly from rcS
    
    # 1. Wait for 15 seconds to ensure all hardware is fully initialized.
    sleep 15
    
    # 2. Directly execute the core commands, ensuring correct working directory.
    (cd /usr/bin/wifiAP && ifconfig wlan0 192.168.4.3)
    (cd /usr/bin/wifiAP && dnsmasq -C dnsmasq.conf)
    (cd /usr/bin/wifiAP && hostapd hostapd.conf -B)
    
    # -----------------------------------------------------------------------------
    

    这个方法的核心在于:

    • 直接:不再有任何中间调用,也就是不在通过/etc/init.d/rcS去调用S60wifi_ap,而是让rcS直接执行最根本的三个命令。

    • 延时:通过 sleep 15 给予系统充足的时间,让所有硬件和底层服务都准备就绪,避免了任何时序问题。

    • 可靠rcS是系统无论如何都会执行的脚本,把命令放在这里可以保证它一定会被执行。

  3. 保存文件,重启开发板。

六、 结语

终于,随着开发板的重启,开机后自动散发了热点,熟悉的 alientek_softap 热点终于自动出现了,手机连上后也顺利获取到了IP地址。至此,整个WiFi AP热点的配置与调试工作画上了圆满的句号。

从最初的配置文件语法错误,到核心的服务启动逻辑顺序问题,再到最后与系统启动流程的“斗智斗勇”,整个过程虽然曲折,但每解决一个问题,对嵌入式Linux系统服务和启动流程的理解就更深了一层。希望这篇踩坑记录能对后来者有所帮助

希望这篇踩坑记录能对大家有所帮助!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值