udhcpc需配合自定义脚本实现DHCP获取IP、DNS写入、失败回退静态IP及防止DHCP抢夺;关键在于-s指定脚本、-t -T控制重试、启动前清空接口、停进程并删租约文件以维持静态配置。

Linux系统下用udhcpc获取IP并写入内核网络栈
嵌入式Linux设备通常不跑完整的NetworkManager,udhcpc是最轻量、最可控的DHCP客户端。它不依赖dbus或systemd,适合资源受限环境,且支持自定义脚本处理IP分配全过程。
关键点在于:不能只调用udhcpc -i eth0就完事——默认行为不会持久化配置,断电重启后失效;更危险的是,它不自动处理“DHCP失败后切静态IP”的逻辑。
- 必须配合
-s参数指定自定义脚本(如/usr/share/udhcpc/default.script),所有IP变更、租约获取、超时失败都由该脚本响应 -
udhcpc本身不写/etc/resolv.conf,DNS需在脚本里手动写入,否则ping通IP但无法解析域名 - 务必加
-t 3 -T 5(最多试3次,每次超时5秒),避免卡死在无DHCP服务器的网络中 - 启动前先清空接口:
ip addr flush dev eth0,否则旧IP和新DHCP地址共存,路由混乱
在udhcpc脚本里实现DHCP失败自动切静态IP
核心逻辑不在C++代码里,而在udhcpc调用的shell脚本中。C++程序只需监听/proc/sys/net/ipv4/conf/eth0/forwarding或定期读ip addr show eth0判断当前IP是否为DHCP获取,但回退动作必须由脚本完成——因为只有它知道DHCP是否真正失败。
典型做法是在脚本的deconfig和leasefail分支里触发静态配置:
立即学习“C++免费学习笔记(深入)”;
#!/bin/sh
# /usr/share/udhcpc/default.script
[ "$1" = "leasefail" ] && {
echo "DHCP failed, fallback to static IP"
ip addr flush dev $interface
ip addr add 192.168.1.100/24 dev $interface
ip link set $interface up
echo "nameserver 8.8.8.8" > /etc/resolv.conf
exit 0
}
[ "$1" = "bound" ] && {
# 正常DHCP流程:设置IP、网关、DNS
ip addr flush dev $interface
ip addr add $ip/$subnet dev $interface
[ -n "$router" ] && ip route add default via $router
[ -n "$dns" ] && echo "nameserver $dns" > /etc/resolv.conf
}注意:leasefail只在重试全部失败后触发,不是每次超时都进;而deconfig会在DHCP释放或接口down时调用,适合清理现场。
C++程序如何可靠检测当前IP来源并参与决策
别试图在C++里轮询DHCP进程状态——udhcpc是独立进程,没有标准IPC接口。可靠方式是检查内核网络状态本身:
- 读取
/proc/sys/net/ipv4/conf/eth0/forwarding没用,这是转发开关;真正要看的是/proc/sys/net/ipv4/conf/eth0/arp_ignore?不对——直接读ip addr show eth0输出更实在 - 用
popen("ip -j addr show eth0 2>/dev/null", "r")解析JSON(需busybox支持-j)或正则匹配inet行,提取IP+掩码 - 对比该IP是否落在预设静态段(如
192.168.1.0/24),再结合/var/lib/udhcpc/eth0.leases是否存在有效租约文件,判断是否为DHCP所得 - 若需C++主动触发回退(比如用户按键强制切换),应
killall udhcpc && sh /path/to/fallback.sh,而非自己调ioctl配IP——重复造轮子易出错
静态IP回退后如何避免DHCP再次抢夺控制权
最容易被忽略的一点:udhcpc默认后台运行,哪怕你已切静态IP,它仍可能在租约续期时突然把IP改回去——尤其当网络里突然出现DHCP服务器时。
解决方法只有两个,且必须同时做:
- 停掉udhcpc:
killall udhcpc,不能只kill一个PID,它可能多实例 - 删掉租约缓存:
rm -f /var/lib/udhcpc/eth0.leases,否则下次启动udhcpc会尝试续租旧地址,导致冲突 - 如果产品要求“插上网线自动DHCP,拔掉切静态”,得用
udev规则监听net/eth0/online变化,而不是让C++轮询
没有“DHCP失败后永久禁用”的内置机制,所有状态维持都靠外部脚本和文件系统标记,这点必须在设计初期就接受。


















