我需要一种方法,在网络接口被启用或禁用时通知我的用户空间应用程序。我希望不使用轮询来完成这个功能。内核是否提供某种钩子以在发生与网络相关的事件时触发回调函数?
我需要一种方法,在网络接口被启用或禁用时通知我的用户空间应用程序。我希望不使用轮询来完成这个功能。内核是否提供某种钩子以在发生与网络相关的事件时触发回调函数?
我认为 netlink (man 7 netlink
) 工具可以通过 NETLINK_ROUTE
家族(man 7 rtnetlink
) 提供有关网络接口的信息。您可以尝试在netlink套接字上使用 select()
或 poll()
方法来获取所需信息。不过我不能确定这一点,因为我自己没有使用过。
更高级别的是,如果系统运行 NetworkManager ,那么当系统网络状态改变时,它将通过 D-Bus 广播事件。例如,Epiphany 浏览器使用这些事件,在系统失去网络连接时自动激活“脱机工作”模式,并在网络连通性恢复时切换回在线模式。有各种语言的 D-Bus 客户端库可用,而且它比 netlink 更少受平台限制,所以我建议使用这个方法。
选项:
ifplugd
会在插入或拔出网络接口电缆时运行您选择的脚本。
如果您正在使用Debian,可以将脚本添加到/etc/network
子目录中,其中有一些脚本会在每次接口启动或关闭时运行。
如果以上两种方法都不适合您的需求,请考虑使用D-Bus。我从来没有成功地使用过它,但这就是它设计的那种东西。
如果不使用轮询或依赖于像Norman Ramsey建议的OS钩子,您唯一的选择是定期检查工作接口与几秒钟前的状态。如果想要在链接不可用时排队/阻塞等待聊天,则只会导致事件/rx/tx队列混乱。
此外,Debian脚本与init脚本配合使用,它们提供的钩子不会告诉您root是否使用ifconfig关闭或修改已配置的接口,或者配置了一个未在init中描述的新接口。它们只会告诉您用户是否通过/etc/init.d/networking执行了某些操作,或者init是否执行了相同的操作。
启动线程以轮询更改有什么可怕的地方吗?
除此之外,是的,您可以启动一个“netnicmond”进程,向订阅者发出信号,让他们知道某些更改,或者更复杂的进程实际上传达了这些更改。您可能会使用netlink进行此操作...
您考虑过只使用netlink吗?
为什么不在代码中使用fork
,并使用popen
执行以下操作:
tail -f /var/log/messages
以查找eth*
接口ifconfig
以查看正在上下线的适配器列表并使用pregex
解析数据,进行sleep()
一段时间后重新检查...或者您可以使用'syslog.h'函数监视系统日志设施。
如果坚持遵循Posix标准,则代码将在不同版本的Unix/Linux/BSD之间可移植...
ifconfig
不符合POSIX标准,且在不同的UNIX系统上输出结果差异很大。当然,在所有Linux系统上它大部分都是相同的,但即便是在那里,也有两个不同版本常见使用(Busybox和net-tools)。 - ephemient/var/log/messages
不是您可以依赖作为任何类型的 API 的文件。它是用于人类可读的日志记录。在某些系统上,日志会转到 /var/log/syslog
。谁知道日志是否可能位于不同的文件名、被禁用或以不同于预期的文本格式存在。程序可能会因其他引用 eth*
的日志条目而感到困惑。 - Craig McQueen