用户空间使用Linux 数据结构系列导读篇

我们知道许多复杂数据结构,都是由一些简单数据对象组成。这些简单的对象可以被增加至该结构,也可以从中删除。实现复杂数据结构的比较好的方法是使用抽象数据类型。

抽象数据类型的主要思想是把一个数据结构的实现完全封装起来,并且只提供一套健壮的接口来操纵它。这样做的好处是做到了干净的隔离。实现数据结构时完全不必了解谁来使用它,使用者也不必知道数据结构的内部实现。双方都只要基于接口来实现代码。

另一方面,由于接口的抽象特性带来了一定的代价。抽象一个接口的关键是去除不必要的细节。虽然从某个角度来说,这带来了一些好处,但是对于Linux内核程序员来说却有问题了。对于Linux内核编程来说,性能非常重要(仅次于正确性和可维护性,或者超过可维护性)。不是所有的内核代码都是性能关键路径,但是大多数都是。而且同一个数据结构既被用于性能关键路径也被用于非关键路径。所以数据结构不能完全抽象化,所有的实现细节必须对程序员可见,这样他们才能用最佳的手段使用数据结构。

Linux内核代码给了我们很好的启示,用一些经典的宏和封装的数据结构及对外接口,来构建内核一些复杂的数据结构,Linux内核的技巧是封装一些通用的数据结构,并把这个通用结构以通用对象定位器(通用结构的指针)的方式,把它嵌入到复杂的数据结构中,然后后围绕定位器建立数据结构。通过定位器以及container_of()就能找到相应的对象(稍候你就会看到这个技巧)。通常通用的数据结构提供了丰富的接口,试图把所有可能性都压缩后放入一个狭窄的接口会无法满足所有的可能性。把所有的变数都考虑到的丰富接口可以鼓励开发人员使用最适合的工具来完成工作,而不是寻找折衷方案。这是很好的策略,在Linux Kernel 2.6.30内核中,list_for_each_entry()用了3000次,list_for_each_entry_safe()1000 次,list_for_each()用了500次。其他剩余的一共使用了1000次。事实证明,就算有些接口很少使用,但不能证明它们是不重要的。

因为Linux内核中这些通用的数据结构,有很好的性能与独立性,而我们在应用程序中也会经常用到这些数据结构,如果我们理解了Linux内核这些数据结构的实现原理与代码,并能向内核开发者一样遵守一些约定,那么无论我们今后编写应用程序,还是贡献内核代码,我们都有了很好的基础,总之,我们的目标是:理解它、学习它、改造它、应用它。

我们会围绕这个话题进行详细的讨论,接下来我会分为几篇文章来讨论以下内容:

l        <<用户空间使用Linux通用数据结构之链表>>  include/linux/list.h

l        <<用户空间使用Linux通用数据结构之环形链表>> include/linux/circ_buf.h

l        <<用户空间使用Linux通用数据结构之哈希表>> include/Linux/list.h

l        <<用户空间使用Linux通用数据结构之红黑树>> include/linux/rbtree.hlib/rbtree.c

l        <<用户空间使用Linux通用数据结构之基树>> include/linux/radix-tree.h lib/radix-tree.c


在我们展开之前,我们先看一下,下面这张图

用户空间使用Linux 数据结构系列导读篇_第1张图片

这张图中给出了我们在什么时机,使用哪种算法,详细的分析内容,我们会在上述文章中展开并实践。

另外,我们会以一种清松的方式来讨论内核这些结构与算法,其中穿插大量的图文,并有恰当的比喻,希望大家能够喜欢。敬请期待!

 

<<用户空间使用Linux通用数据结构之红黑树>>篇将出场的人物有:

 

用户空间使用Linux 数据结构系列导读篇_第2张图片

你可能感兴趣的:(数据结构,算法,linux,list,each,linux内核)