IT技术博客大学习 共学习 共进步

标签:Linked List

共 3 篇相关文章

IT 累计浏览 13,162

Linus:利用二级指针删除单向链表

这篇讲的是Linus Torvalds如何用二级指针来优雅地删除单向链表节点。文章从Linus在slashdot上对一段“标准”代码的批评切入,他直言那种需要维护`prev`指针并判断是否为表头的写法,表明作者“不懂指针”。 核心对比了两种实现思路。传统写法(很多教科书和面试题的标准答案)需要额外维护一个`prev`指针,并在删除时判断当前节点是否为链表头,代码中存在条件分支。而Linus推崇的“core low-level coding”技巧,是直接使用一个指向节点指针的指针(即二级指针`node** curr`)来遍历和操作链表。其精妙之处在于,无论要删除的是表头还是中间节点,都可以通过统一的`*curr = entry->next`操作完成,无需任何条件判断。文章通过逐行代码解析和示意图,阐明了这种写法如何将“前驱指针”的概念融入到对`next`指针本身的间接操作中,最终生成更清晰、更可能被编译器优化出高效指令的代码。 这种对指针的深刻理解和运用,体现了Linus所看重的注重细节、追求高效底层编码的审美。

IT 累计浏览 3,583

浅析Linux Kernel中的那些链表

这篇讲的是Linux内核中链表的实现。作者从内核开发者最熟悉的链表结构切入,指出它与数据结构教材中的标准链表有着本质区别。 文章的核心在于剖析内核链表的巧妙设计。它并非传统意义上“节点包含数据”,而是采用侵入式设计:链表节点(`list_head`)被嵌入到你想要管理的数据结构本身中。这样,一套通用的链表操作代码就能管理任意类型的数据,无需为每种数据重写实现。 作者详细对比了侵入式链表与非侵入式链表的差异。传统链表需要为数据分配单独的节点内存,而内核链表将节点与数据合为一体,在内存管理上更为高效和灵活。这种设计使得通过一个数据结构中的链表节点,可以反向定位到包含它的整个结构体,这是理解后续很多内核数据结构(如进程队列)的关键。 文章最后可能总结,这种设计牺牲了一点点直观性,但换来了极大的通用性、性能和内存效率,是内核编程中“空间与时间”、“通用与专用”权衡的经典范例。对于想深入理解内核源码的开发者来说,厘清这个基础结构至关重要。

IT 累计浏览 3,983

开源世界中的算法与数据结构 3 -- Linux Kernel List 和GList

这篇讲的是 Linux 内核和 GLib 中两种经典链表实现的设计哲学与实践权衡。作者没有纠缠于基本的增删操作,而是从工程实现的底层逻辑出发,对比了它们的差异。 核心差异在于内存模型:Linux 内核链表是侵入式的,它不另立节点存储数据,而是将 `list_head` 结构体直接“嵌”到你的数据结构里,通过 `container_of` 宏从节点反推出宿主对象。这带来了极致的内存效率和访问速度,节点与宿主数据一体,缓存友好。但代价是链表节点不能脱离宿主数据独立存在。 相反,GLib 的 `GList` 是通用的、非侵入式的。每个节点都是独立的内存块,通过 `prev` 和 `next` 指针串联,节点里用一个 `gpointer data` 指向实际数据。这带来了灵活性——节点可以被多个链表共享,生命周期也容易管理。但每一次插入、删除或访问数据,都需要额外的指针解引用,在性能敏感的内核路径上可能无法接受。 文章正是通过这两种截然不同的设计,揭示了在“通用性/灵活性”与“高性能/低开销”之间做选择时的典型工程考量。读完能理解,为何没有完美的链表,只有最适合特定场景的实现。