为什么 Linux 内核使用它所使用的数据结构?

Why does the Linux Kernel use the data structures that it does?

Linux内核对TCP使用链表,对进程调度使用RB树。

就算法效率而言,这些是有道理的。您将一次获得一堆数据包,因此在列表末尾插入 O(1) 很好。

对于进程调度,Completely Fair Scheduler 使用红黑树,O(1) 时间来选择任务。

据我所知,这些都不是以 'flat' 方式实现的——链表是一堆节点和指向其他节点的指针,就像树一样。这意味着据我所知,这些结构的局部性应该很差。

据我所知,缓存局部性通常比算法效率更重要。

Linux 编程的数据集是否有某些东西使得这些结构的算法效率超过其他结构的缓存效率?

我是不是误会了什么?有人介绍过吗?

关于链表的使用,我有一个部分的答案,我相信你会在this page about the CFS scheduler中找到一些有趣的信息,特别是它提到了红黑树has good worst-case time for operations such as insert, search, and delete确实对于调度程序来说似乎是一个非常理想的 属性。

我敢打赌,是的,内核已经进行了大量分析,而且这些数据结构似乎在现实世界中表现良好。

This blog post 有一些关于内核链表使用的很好的数据。这些数据显然是在 3 天的正常使用中通过保持每次操作完成的计数器来收集的。

+--------------------+-----------+
|     Operation      | Frequency |
+--------------------+-----------+
|     Empty Test     | 45%       |
|       Delete       | 25%       |
|        Add         | 23%       |
|   Iterate Start    | 3.5%      |
|   Iterate Next     | 2.5%      |
|     Replace        | 0.76%     |
| Other Manipulation | 0.0072%   |
+--------------------+-----------+

如你所见,实际访问元素的操作只占总数的6%,而插入和删除操作加起来几乎占了一半。这是一个链表开始变得更有意义的用例。请注意,数据是在整个内核中收集的,而不是专门针对 TCP 代码,因此每次使用链表的理由可能并不相同,但汇总数据确实表明这些选择总体上是明智的。

我认为记住内核的设计必须能够从最小的嵌入式设备扩展到处理大量数据的超级计算机也很重要,此时算法效率可能开始严重超过缓存问题。