内核的很多子系统之间有很强的依赖性,其中一个子系统侦测到或者产生的事件,其他子系统可能都有兴趣,为了实现这种交互需求,linux使用了所谓的通知链。
本章我们将看到
通知链如何声明以及网络代码定义了哪些链
内核子系统如何向通知链注册。
内核子系统如何在链上产生通知信息。
注意,通知连只在内核子系统之间使用,内核和用户空间之间的通知信息则是依赖其他机制,如第三章所介绍的那些。
使用通知链的原因。
假设我们有如图4-1所示的带有四个接口的linux路由器,此图显示了路由器与五个网络之间的关系,还有一份简化路由表。
让我们看看图4-1拓扑结构的几个例子,网络A直接连接到RT的接口eth0,而网络F没用直接链接到RT。但是RT的eth3则直接连到另一个路由器,其他接口的地址为IP1,并且第二个路由器知道该如何联系网络F,其他的案例都很类似。简而言之,有些网络是直接连接的,而其他的网络则需要一个或者多个附加的路由器协助才能联系得到。
有关路由代码如何处理这种情况的详细描述,可参考第七部分,本章的焦点是通知链的角色。假设接口eth3由于网络断线使得管理命令失效或者造成硬件失败,结果RT无法联系网络D,E和F,因此应该从路由表中删除。谁将通知路由子系统该接口的失效,那就是通知链。
上图是稍微复杂的例子,路由子系统会与动态路由协议交互,这种协议可以调整一个或者多个路由表,使其吻合网络拓扑结构,因此当拓扑结构许可的时候就可以处理接口失败的问题。
上图中,RT可以通过网络A和网络E而联系网络F,最初会选E是因为其成本较少,但是现在E已经无法联系,因此,路由比哦啊应该更新网络F的路由改走网络A,这种决策的基础可能包括一些本地主机事件,诸如设备注册和删除,以及路由配置中的复杂因素和所用的路由协议。在任何情况下,管理路由比哦啊的路由子系统必须从其他子系统那里收到相关的信息的通知,因而产生了通知链的需求。
概论
通知链就是一份简单的函数列表,当给定事件发生的时候予以执行。每个函数都让另一个子系统知道,调用此函数的子系统内所发生的一个事件或者子系统侦测到的一个事件。
因此,就没调通知链而言,都有被动端和主动端,也就是所谓的发布--订阅模型。
被通知就是要求接收某事件的子系统,而且会提供回调函数予以调用。
通知者 就是感受到一个事件并调用回调函数的子系统。
所执行的函数是由被通知的子系统所选取,绝不是链条的拥有者决定该执行什么函数。拥有者只是定义这份列表而已,任何内核子系统都可以对该链条注册一个回调函数以接收通知信息。
通知链的使用源码更易于编写和维护,想象一下,一个通用的函数不使用通知链该如何把一个事件通知给外部子系统。
if (subsystem_X_enabled)
do_something_1
if (subsystem_Y_enabled)
do_something_2
if (subsystem_Z_enabled)
do_something_3
换言之,必须为每个可能对一个事件感兴趣的子系统都引入一个条件子句,结果每次添加一个子系统给内核时,子系统的维护就得添加一个子句。
子系统维护者不可能去追踪每个被添加到内核的咨询哦太难过,然而,每位子系统维护者都应该知道。
1 自己对来自其他子系统的哪种事件感兴趣
2 自己知道的事件有几种,并且其他子系统可能感兴趣的事件又是哪几种。
因此,通知链允许每个子系统和其他咨询哦太难过共享发生的事件,而无需知道究竟是哪些子系统产生事件,以及那些子系统为什么感兴趣。