通用(内核)链表详解

Linux内核中充斥着大量的数据结构,这些数据结构很多都是使用结构体来表示:如cdev结构体用于描述一个字符设备,再如task_struct结构体,是我们所说的进程控制块PCB,用于描述一个进程的所有信息。追寻内核源码我们会发现很多都是表示设备的结构体中都有list_head这样的字段,没错这就是内核链表的节点类型。描述设备的结构体中只要包含这个字段,内核就能通过链表来管理我们的设备,试想浩瀚的内核中有大量不同类型的设备或结构体,如何把他们统一起来进行管理呢?内核链表在这里就立下了汗马功劳,它的设计非常的巧妙,也体现了内核设计者的强大的智慧,下面跟随我的脚步来探寻下内核链表(以下都叫做通用链表)是如何实现的,又是如何管理我们不同类型的结构体的。
首先我们讨论下普通的链表的特点:和数组相比它的节点内存分配可以是不连续的,可以动态的增减节点也就是链表长度可以不固定,但是它的数据域在定义链表节点的时候必须固定,也就是说普通的链表只能维护一条相同的数据类型的节点,如果数据域长度改变必须重新定义链表节点。
内核中由于要管理大量的设备,但是各种设备各不相同,必须将他们统一起来管理,于是内核设计者就想到了使用通用链表来处理,通用链表看似神秘,实际上就是双向循环链表,这个链表的每个节点都是只有指针域,没有任何数据域。
这里写图片描述
图1 普通的单链表
使用通用链表的好处是:1.通用链表中每个节点中没有数据域,也就是说无论数据结构有多复杂在链表中只有前后级指针。2.如果一个数据结构(即是描述设备的设备结构体)想要用通用链表管理,只需要在结构体中包含节点的字段即可。3.双向链表可以从任意一个节点的前后遍历整个链表,遍历非常方便。4.使用循环链表使得可以不断地循环遍历管理节点,像进程的调度:操作系统会把就绪的进程放在一个管理进程的就绪队列的通用链表中管理起来,循环不断地,为他们分配时间片,获得cpu进行周而复始的进程调度。
这里写图片描述
图2 通用链表

有了这些理论的东西,下面我们来实现一下通用链表,并使用它来管理一个学生信息的结构体。其他类型的任何结构体管理亦是如此。我们会把主要的注释放在程序代码中,结合图示来进行阐述。
以下是list_head.h文件,描述通用链表的节点类型和操作函数的声明。

#ifndef __LIST_HEAD_H__
#define __LIST_HEAD_H__

//通用链表节点类型  双向链表
struct list_head{
    struct list_head *prev; //前级指针
    struct list_head *next;//后级指针
};

void INIT_LIST_HEAD(struct list_head *list);//初始化通用链表
void l
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值