【C 高阶】C 的类泛型编程 -- Linux 内核链表

1. 链表简介

由于 C 语言为面向过程的语言,标准库中并没有提供数据结构相关的数据类型。因此,当需要在程序使用链表结构时,只能从 0 开始实现一个链表类型,且设计的质量参差不齐。

在 Linux 内核中提供了一个通用的链表节点类型 struct list_head,该链表为循环双向结构,并配套了一系列维护链表结构的 API。

在程序中,只需在定义结构体时包含一个 struct list_head 类型的成员,该自定义结构体类型就能变作为链表节点的类型。通过对应的 API 操作 struct list_head 类型的成员变量,就能对链表进行管理维护。

如果把节点类型中 struct list_head 类型的成员变量看作链表类中节点类的公有成员变量,把除 struct list_head 类型外的成员变量看作为链表类中节点类的泛指类型的成员变量,把一系列 API 看作为链表类的成员函数,那么 Linux 内核链表将可以看作为一个双向循环链表类。

实际上,Linux 内核链表就是面向对象的类泛型编程的方法。


2. 节点类型

struct list_head 中只包含两个成员:前指针与后指针。

struct list_head 
{
   
    struct list_head* next;
	struct list_head* prev;
};

在自定义节点类型时,只需包含一个 struct list_head 类型的成员变量,将等效于包含了节点的前后指针,即该成员变量为链表节点间实际相连的指针。

同时,使用 API 管理链表时所操作的对象也必须是节点中 struct list_head 类型的成员变量。


3. 常用 API

与 Linux 内核链表相关的文件中,<LinuxList.h> 为最核心的头文件,提供了相对应的增删改查 API ,其又依赖的头文件有:<linux/types.h>、<linux/stddef.h>、<linux/poison.h>、<linux/prefetch.h>。

由于 Linux 与 GNU 一脉相承,Linux 内核链表中使用了 GNU 所扩展的语法,例如关键字 typeof 与双括号语法。如果需要在不支持 GNU 的平台(如 msvc)上使用 Linux 内核链表,可以把 GNU 所扩展的语法移除和把 prefetch() 函数省略,提取出核心的源码。这样也并不影响链表的正常使用,只会提升一些调用时的安全风险。

在这里将对最核心的 API 进行一一介绍。

3.1 初始化

  • API:
static void INIT_LIST_HEAD(struct list_head* head)
{
   
    head->next = head;
    head->prev = head;
}
  • 使用说明:

在定义一个链表节点后,使用 INIT_LIST_HEAD 对链表节点进行初始化,此时该节点将作为链表的头节点,即创建了一个链表对象。需要注意的是,在 Linux 内核链表类型中,链表的头节点仅作为链表的管理者,并不参与实际的数据存储。

3.2 插入

  • API:
static void __list_add(struct list_head* new_node,
					   struct list_head* prev,
					   struct list_head* next)
{
   
    next->prev = new_node;
    new_node->next = next;
    new_node->prev = prev;
    prev->next = new_node;
}

static void list_add(struct list_head* node, 
					 struct list_head* head)
{
   
    __list_add(node, head, head->next);
}

static void list_add_tail(struct list_head* node, 
						  struct list_head* h
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值