Linux下查看路由表最快方式是ip route show,现代发行版默认安装、输出结构化;旧系统可退化为route -n,但字段格式不同;需捕获输出时应使用popen()而非system()。

Linux 下用 system() 调用 ip route 最快出结果
直接读取内核路由表需要解析 /proc/net/route 或调用 netlink(复杂且易错),而大多数运维/调试场景只需“显示当前生效的路由”,此时绕过底层、复用系统命令更稳。用 system("ip route show") 一行就能拿到人类可读的输出,适合快速验证或日志记录。
注意:ip route 是 iproute2 套件命令,现代 Linux 发行版默认安装;若旧系统只有 route -n,可改用 system("route -n"),但格式略有不同(列顺序和字段名不一致)。
-
system()不捕获输出,仅打印到终端——如需后续处理(比如提取某条路由的网关),得换popen() - 确保程序有执行 shell 命令的权限(容器环境可能被禁用)
- 别在高频率循环里反复调用,
ip route本身开销小,但 fork+exec 有成本
Windows 下必须用 GetIpForwardTable()(IPv4)或 GetIpForwardTable2()(IPv6)
Windows 没有标准命令行路由 dump 工具能稳定覆盖所有接口类型(route print 输出格式不固定,多网卡时容易错行),必须走 Win32 API。核心是获取 MIB_IPFORWARDTABLE 结构体数组,每项含 dwForwardDest(目标)、dwForwardNextHop(下一跳)、dwForwardIfIndex(接口索引)等字段。
关键点:
立即学习“C++免费学习笔记(深入)”;
- 调用前先
#include <iphlpapi.h></iphlpapi.h>并链接Iphlpapi.lib -
GetIpForwardTable()只支持 IPv4;IPv6 必须用GetIpForwardTable2(AF_INET6, ...) - 返回的 IP 地址是网络字节序,需用
ntohl()转主机序再格式化为点分十进制 - 接口索引要配合
GetIfEntry()才能查到对应网卡名(否则只显示数字)
跨平台封装时别硬写 if-else,优先检查 /proc/net/route 是否存在
想写一份代码跑 Linux 和 WSL?别一上来就 #ifdef _WIN32。实际更可靠的做法是:先尝试打开 /proc/net/route,存在则按 Linux 格式解析;不存在再 fallback 到 Windows API 路径。因为 WSL1/WSL2 的 /proc 是完整的,而某些嵌入式 Linux 可能没挂载 procfs,这时反而该走 netlink。
/proc/net/route 解析要点:
- 第一行是表头(如
Iface\tDestination\tGateway\t...\tMetric\t...),需跳过 - Destination/Gateway 字段是十六进制(小端),例如
00000000表示 0.0.0.0,0100007F表示 127.0.0.1(注意字节序翻转) - Metric 值为 0 表示直连路由,非 0 通常是静态或动态学习到的路由
- 不要依赖列数固定——不同内核版本字段数可能增减(比如新增
Use或Window列)
用 netlink(Linux)或 MIB-II(Windows)做实时监听会踩一堆坑
如果需求是“路由变化时立刻通知”,别自己轮询 ip route 或定时读 /proc/net/route。Linux 应监听 NETLINK_ROUTE socket 的 RTM_NEWROUTE/RTM_DELROUTE 消息,Windows 应用 NotifyRouteChange2() 注册回调。但这两种方式都极易出错:
- netlink 需手动构造
struct nlmsghdr,漏设NLM_F_REQUEST | NLM_F_DUMP位会导致收不到初始快照 - Windows 的
NotifyRouteChange2()回调运行在新线程,若回调里调用 UI 函数(如printf)且主线程已退出,会 crash - 两者都要求进程有 CAP_NET_ADMIN(Linux)或 SeNetworkConfigurationPrivilege(Windows)权限,普通用户默认没有
真实项目里,90% 的“监听”需求其实只需要每 5 秒 ip route show 一次 diff,既简单又足够用。



















