在Linux上如何获取有关网络接口更改的通知

21

我需要一种方法,在网络接口被启用或禁用时通知我的用户空间应用程序。我希望不使用轮询来完成这个功能。内核是否提供某种钩子以在发生与网络相关的事件时触发回调函数?


2
关于'rtnetlink',您可以查看以下链接获取示例代码:https://dev59.com/7HRB5IYBdhLWcg3wl4EQ#2353441 - fanyangxi
4个回答

28

我认为 netlink (man 7 netlink) 工具可以通过 NETLINK_ROUTE 家族(man 7 rtnetlink) 提供有关网络接口的信息。您可以尝试在netlink套接字上使用 select()poll() 方法来获取所需信息。不过我不能确定这一点,因为我自己没有使用过。

更高级别的是,如果系统运行 NetworkManager ,那么当系统网络状态改变时,它将通过 D-Bus 广播事件。例如,Epiphany 浏览器使用这些事件,在系统失去网络连接时自动激活“脱机工作”模式,并在网络连通性恢复时切换回在线模式。有各种语言的 D-Bus 客户端库可用,而且它比 netlink 更少受平台限制,所以我建议使用这个方法。


例如,请参见 Stack Overflow 问题“How to detect IP address change programmatically in Linux?”的此答案 - Craig McQueen

11

选项:

  • ifplugd会在插入或拔出网络接口电缆时运行您选择的脚本。

  • 如果您正在使用Debian,可以将脚本添加到/etc/network子目录中,其中有一些脚本会在每次接口启动或关闭时运行。

  • 如果以上两种方法都不适合您的需求,请考虑使用D-Bus。我从来没有成功地使用过它,但这就是它设计的那种东西。


-1

如果不使用轮询或依赖于像Norman Ramsey建议的OS钩子,您唯一的选择是定期检查工作接口与几秒钟前的状态。如果想要在链接不可用时排队/阻塞等待聊天,则只会导致事件/rx/tx队列混乱。

此外,Debian脚本与init脚本配合使用,它们提供的钩子不会告诉您root是否使用ifconfig关闭或修改已配置的接口,或者配置了一个未在init中描述的新接口。它们只会告诉您用户是否通过/etc/init.d/networking执行了某些操作,或者init是否执行了相同的操作。

启动线程以轮询更改有什么可怕的地方吗?

除此之外,是的,您可以启动一个“netnicmond”进程,向订阅者发出信号,让他们知道某些更改,或者更复杂的进程实际上传达了这些更改。您可能会使用netlink进行此操作...

您考虑过只使用netlink吗?


-4

为什么不在代码中使用fork,并使用popen执行以下操作:

  • 发出tail -f /var/log/messages以查找eth*接口
  • 发出ifconfig以查看正在上下线的适配器列表

并使用pregex解析数据,进行sleep()一段时间后重新检查...或者您可以使用'syslog.h'函数监视系统日志设施。

如果坚持遵循Posix标准,则代码将在不同版本的Unix/Linux/BSD之间可移植...


2
ifconfig不符合POSIX标准,且在不同的UNIX系统上输出结果差异很大。当然,在所有Linux系统上它大部分都是相同的,但即便是在那里,也有两个不同版本常见使用(Busybox和net-tools)。 - ephemient
/var/log/messages 不是您可以依赖作为任何类型的 API 的文件。它是用于人类可读的日志记录。在某些系统上,日志会转到 /var/log/syslog。谁知道日志是否可能位于不同的文件名、被禁用或以不同于预期的文本格式存在。程序可能会因其他引用 eth* 的日志条目而感到困惑。 - Craig McQueen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接