直接读取/proc/net/dev是最简单可靠的方案,因其字段稳定、无需root、无依赖且比netlink/ioctl更轻量;需跳过前两行表头,用std::istringstream解析每行,提取第2列rx_packets和第10列tx_packets(索引从0起),以uint64_t存储防溢出。

要获取 Linux 系统中网络接口的实时进出流量包计数(如 eth0 的接收/发送数据包总数、错误包、丢弃包等),需直接读取内核暴露的 procfs 接口 /proc/net/dev,该路径下内容由内核网络子系统实时更新,无需额外权限或驱动,且无采样延迟。
读取 /proc/net/dev 获取原始流量包统计
打开终端,执行:
cat /proc/net/dev
输出中第二行起为各接口统计行,字段顺序固定:Interface→Receive bytes→packets→errs→drop→fifo→frame→compressed→multicast→Transmit bytes→packets→errs→drop→fifo→collisions→carrier→compressed。其中第2列(packets)为接收总包数,第10列为发送总包数,单位均为无符号 64 位整数。
注意:第一行是表头,含 16 个字段;实际接口行以空格或制表符开头,但字段间用一个或多个空白符分隔——【必须用 std::istringstream 或 strtok_r 按空白符分割,不能按固定列宽截取】。
用 C++ 解析并差值计算实时包速率
步骤一:定义结构体存储两次采样值
struct IfaceStats { uint64_t rx_packets = 0; uint64_t tx_packets = 0; };
步骤二:编写 parse_dev_line 函数,跳过首行,对每行调用 std::istringstream 提取 interface 名与第2、第10字段;若 interface == "eth0"(或目标接口),则赋值到 IfaceStats 对象。
步骤三:第一次读取 /proc/net/dev → 存入 stats_old;sleep(1);第二次读取 → 存入 stats_new;计算差值:rx_delta = stats_new.rx_packets - stats_old.rx_packets;同理得 tx_delta。这即为 1 秒内收发包速率(pps)。
这一步操作起来很简单,直接把文件拖进去就行。但要注意:若两次读取间隔小于 10ms,部分网卡驱动可能未更新计数器,导致 delta 为 0;建议最小采样间隔设为 100ms 以上。
内核级监控接口原理分析
方法一:/proc/net/dev 数据来源
内核在 net/core/dev.c 中维护每个 net_device 结构体的 struct rtnl_link_stats64 成员,每次软中断收包(napi_poll)、驱动发包完成(ndo_start_xmit 回调)时原子更新 rx_packets/tx_packets 字段;proc_do_devs 函数将其格式化输出,无锁、无拷贝、零分配。
方法二:替代接口对比
/sys/class/net/eth0/statistics/ 目录下有 rx_packets、tx_packets 等文件,其值与 /proc/net/dev 一致,但每次 open+read 触发一次内核函数调用,开销略高;而 /proc/net/dev 单次 read 可批量获取所有接口数据,更适合高频轮询。
方法三:eBPF 方式(进阶)
若需过滤特定协议包或追踪丢包位置,可加载 eBPF 程序挂载到 tc ingress/egress 或 tracepoint net:net_dev_start_xmit,用 percpu_map 累计计数;但此方式不提供历史累计值,仅适合事件流聚合,无法替代 /proc/net/dev 的基线统计功能。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











