1.前言
《深入理解Linux网络技术内幕》这本书是讲Linux网络的底层原理的,涉及到非常多OS kernel方面的东西。个人阅读这本书的初衷,也是为了对于我们使用的linux机器上的网络底层架构有更深入的了解:比如数据具体是如何从运行在OS中的程序经过协议栈的处理,传输到网卡硬件中的?网卡硬件又是如何在OS的协调下把数据封包发送出去的等等。
了解清楚这个过程中发生的事情和细节,有助于我们在工作中解决实际问题时有一个全局性、逻辑化的视角,在遇到问题或者做性能优化的时候,这些背景知识带来的视角能帮助我们更好地完成我们的目标。
这本书相对我当前阶段来说(只有一些本科的OS基础和少量的linux kernel了解)是比较晦涩的,因此我不打算第一次就把这本书完全啃通,而是打算使用多次迭代地方式。最开始我可能对这本书有50%的理解,不过没关系,我会多次阅读,逐步把内容向100%的方向完全吸收。
因此,我总结出的内容可能无法完全高度概括原书中的内容,更多是侧重于我个人的理解,我也只会详细写比较触动我的地方,如果有其他读者阅读了本篇文章请见谅。
本篇博客总结我阅读深入理解Linux网络技术内幕这本书第二十六章到第三十六章的理解
2.正文
第二十六章到第三十六章主要涉及到了邻居子系统和路由两个大主题
邻居子系统
邻居子系统可以直接被理解为是“L2层的路由”,负责的是在L2层网络中通过逻辑地址(IP)找到物理地址(设备MAC)的过程。协议栈在发送数据时,当上层L3协议提供了L3地址后(一般是IP),协议栈就通过邻居子系统中保存的L2地址和L3地址之间的映射关系,寻找到对应的L2地址,并根据L2地址进行封包发送。同样的,原则上,在协议栈接受数据时,我们也可以通过邻居子系统来获得接受数据包对应的L3地址(如果需要的话)
在传送一个数据包时,首先由本地主机路由子系统选择L3目的地址,如果下一跳在同一网络,邻居层就把L3地址解析为L2地址(通过邻居子系统),并将这个关联放到缓存之中,然后根据L2地址进行本地网络的数据发送。所以说,邻居子系统更多管理的是L2层和L3层之间发生的事情。
常见的邻居协议有ARP和ND协议,前者用于IPv4中,后者用于IPv6中,两者是完全不同的设计,ND是ICMPv6提供的一个函数,但其实两者起到的作用是一致的。
邻居子系统的查找表,对应了L2层和L3层地址之间的映射关联,是个hash表,每一个表项代表一个neighbor情况,保存网络中邻居的状态,并进行网络不可达性检测,为数据在L2层的发送做了充分必要的准备条件。
值得一提的是,邻居子系统的表中保存的每一个neighbor项,都有对应的状态(被称为NUD),通过状态的变化流转,邻居子系统会对每一个neighbor项根据其对应状态进行不同的操作,在访问使用到每一个neighbor项后,对应的结果也和其状态有关。
除了最基本的状态表,为了加速整个邻居子系统的性能,邻居子系统中还有对应的缓存表,来缓存近期经常使用的热点数据。
邻居子系统所做的基本操作就是看到未知的IP地址,就向本地网络广播询问请求,等待IP对应的本地网络中的主机回应(如果有的话),然后将其保存到自己的表中,完成整个操作。除此之外,就是定时检测表中neighbor项的状态情况,根据不同的状态情况做出对应的调整以及响应其他子系统的查询请求。
另外,由于网络中的情况复杂多变,因此邻居子系统也需要进行垃圾回收,这个主要是通过对每一个存在的表项(即neighbor记录)计算引用计数而得到的,系统同时使用同步和异步的垃圾回收来提升整体的性能表现;除此之外,当邻居子系统获知了一些重要的事件发生时(例如邻居位置发生变化或失效),会通过通知链通知给其他相关的子系统,进行进一步的状态调整。
当然,我们也可以通过procfs来进行邻居子系统相关的内核参数配置,对整个系统进行定制化的调整和优化。也可以使用ip neighbor命令在用户空间来直接和邻居子系统交互,譬如手动添加删除neigbor记录等等。
路由
路由子系统最核心的功能就是提供路由信息的查询和维护,数据包要从此处发到某个IP地址,下一跳在哪,发送到路由器的哪个接口,这就需要路由子系统进行协助。
保存路由信息的表就是路由表,Linux中使用两张路由表,一张用来保存本地地址的路由规则,另一张用于外部网络路由规则。查询路由规则时,使用最长前缀匹配算法查询,使用线索树来进行存储和索引。不直接使用哈希表是因为在海量路由数据的情况下,哈希表会存在碰撞和冲突严重的情况,还需要进行动态的rehash,而线索树则不需要,直接通过最长前缀匹配算法查询,避免了此类情况。同样的,为了加速查询路由信息的整体性能表现,路由表也有缓存表,这个就是哈希表了。
Linux中的路由子系统还有一些高级功能,比如策略路由,原本的Linux只有两张路由表,但使用策略路由可以定义多张路由表,每张路由表在不同的触发条件下使用(比如对指定的数据包做特殊标记,来进行对特定路由表的匹配),从而实现更加复杂灵活和多样化可定制的路由控制。
除此之外,还有多路径路由,对于同一个路由,可以为有不同服务质量要求的服务提供不同的路径、分散流量、提供冗余链路等,动态化地利用整个网络上的资源,消除了单路由模式下的种种局限性。
netfiliter的钩子函数一部分也是嵌入到路由子系统的,使用iptable的时候最好要意识到这一点。路由子系统同时也和其他的网络子系统有非常密切的交互,比如网络设备的状态变化,就会引起路由表的添加、删除或是更新,路由缓存同时也要被刷新。另外,一些复杂路由协议的运行(比如OSPF RIP等),需要用户态的路由协议守护进程来支持。
在路由子系统中,同样也存在垃圾回收,并且和邻居子系统的垃圾回收的模式基本相似,都是以引用计数作为基本依据,然后使用异步回收和同步回收并用的策略来提高整体的性能表现。
同样的,对于路由子系统,我们也可以进行灵活的定制化配置,通过ip和route命令在用户空间操作路由子系统,例如添加删除路由信息等。通过procfs调节路由子系统中各个可调节的内核参数,来优化路由系统的整体表现。
3.总结
书本最后这一部分用了大量的篇幅,但却仅仅涉及了两个大的主题,由此可见这两个主题之庞杂。
我上面的文字,仅仅是对这两部分进行了非常粗略性的概括,具体到书中,作者写得非常详细和复杂。但大部分的知识,强行理解记忆的意义并不大,通读这本书下来,在我看来这本书更适合当成一本随时查阅的工具书,或者专心肯内核源码时的参考书,而不适合作为一本体系化的理论学习的书。
不过,整个Linux网络体系,在这本书中是被划分清晰的,通过速读这本书,也在我之前的对网络纯粹的、模糊的、理论化的理解中加入了一些实际和具体的印证。从实际实现的角度,来理解一个实际运行的网络系统是如何被设计、运行起来的。所以,如果真的相对linux网络技术有比较深入的了解,这本书还是需要常读常新的。
另外,这本书的中文翻译确实不怎么样,很多时候甚至让我怀疑是我的理解能力出了问题,上网一查,果然很多人都吐槽这本书的翻译的很差。果然,掌握阅读外文原著的能力还是很重要的。
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://hqyman.cn/post/10505.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~