最新动态
【linux kernel】linux内核数据结构分析之链表
2023-06-28 07:51  浏览:180

👀Linux内核中实现了一套经典的链表操作,定义在/include/linux/list.h文件中,本文基于linux内核源码,记录了其常用操作链表的API函数,便于在阅读linux内核源码时更好的理解程序执行的过程和细节。

定义在/include/linux/types.h文件中

 
 

定义在文件/include/linux/list.h中,下文是操作链表的API,这些API在Linux内核中各个组成子系统中几乎都会看见其声影。

 
 
 
 
 
 
 
 
 

本质是删除和链表初始化的组合

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

list_entry函数宏的作用是根据给定节点的指针和包含它的结构体成员的偏移量,计算并返回包含该节点的结构体的指针。其中,ptr是给定节点的指针,type是包含该节点的结构体类型,member是该节点在结构体中的成员名。

 
 

list_first_entry函数宏的作用是返回链表的第一个节点所在结构体的指针。ptr是指向链表头部的指针,type是包含节点的结构体类型,member是节点在结构体中的成员名。

 

🔺示例代码

 

在上述示例代码中,通过使用list_first_entry宏,可以获取链表的第一个节点所在struct my_struct结构体的指针,并访问其中的成员数据。这样可以方便地获取链表的第一个元素并进行相关操作。

list_last_entry函数宏的作用是返回链表的最后一个节点所在结构体的指针。

 
 

list_first_entry_or_null函数宏的作用是返回链表的第一个节点所在结构体的指针,如果链表为空,则返回空指针。

 
 

list_next_entry函数宏的作用是返回给定节点的下一个节点所在结构体的指针。pos是给定节点的指针,member是节点在结构体中的成员名。

 

🔺使用示例:

 
 

list_next_entry_circular函数宏的作用是返回循环链表中给定节点的下一个节点所在结构体的指针。

 
 

list_prev_entry,用于获取链表中给定节点的前一个节点所在结构体的指针。

该函数宏接受两个参数:pos是给定节点的指针,member是节点在结构体中的成员名。通过调用list_prev_entry函数宏会获取给定节点的前一个节点的指针,然后将其传递给list_entry宏,计算并返回该节点所在结构体的指针

 
 

list_for_each是一个宏定义,在Linux内核中用于遍历双向链表的宏。

list_for_each宏接受两个参数:pos和head。其中,pos是用于迭代遍历链表的临时指针变量,而head是链表的头指针。

使用list_for_each宏可以遍历整个链表,从链表的第一个节点开始,一直迭代到最后一个节点。在每次迭代时,pos指向当前节点的指针。

 
 

list_for_each_rcu宏接受两个参数:pos和head。其中,pos是用于迭代遍历链表的临时指针变量,而head是链表的头指针。

与普通的list_for_each宏不同的是,list_for_each_rcu宏使用了rcu_dereference函数来读取指针的值,以保证在RCU保护下的安全访问。

使用list_for_each_rcu宏可以在RCU保护下遍历链表,从链表的第一个节点开始,一直迭代到最后一个节点。在每次迭代时,pos指向当前节点的指针。

 
 

是一个宏定义,在Linux内核中用于继续之前的双向链表遍历的宏。

该宏的定义如下

 

宏接受两个参数:和。其中,是用于迭代遍历链表的临时指针变量,而是链表的头指针。

使用宏可以在链表遍历过程中继续之前的迭代,从上一个迭代结束的位置的下一个节点开始,直到最后一个节点。在每次迭代时,指向当前节点的指针。

以下是一个示例,展示了如何使用宏继续之前的链表遍历

 

在上述示例中,使用宏在链表遍历过程中继续之前的迭代。在第一次迭代中,访问到节点时,调用宏继续遍历,跳过了节点,从下一个节点继续迭代。

通过使用宏,可以在链表遍历中灵活地控制迭代的流程,例如根据特定条件跳过某些节点,或者在某些节点之后执行额外的操作。这样可以实现更复杂的遍历逻辑和数据处理。

是一个宏定义,在Linux内核中用于逆向遍历双向链表的宏。

该宏的定义如下

 

宏接受两个参数:和。其中,是用于迭代遍历链表的临时指针变量,而是链表的头指针。

使用宏可以逆向遍历整个链表,从链表的最后一个节点开始,一直迭代到第一个节点。在每次迭代时,指向当前节点的指针。

以下是一个示例,展示了如何使用宏逆向遍历链表

 

在上述示例中,使用宏逆向遍历了名为的双向链表。在每次迭代中,通过宏将指针转换为节点所在的结构体的指针,并访问其中的成员数据。

通过使用宏,可以方便地逆向遍历链表并对每个节点执行相应的操作,例如访问节点的数据、进行计算、更新节点等。

是一个宏定义,在Linux内核中用于安全地遍历双向链表的宏。

该宏的定义如下

 

宏接受三个参数:、和。其中,是用于迭代遍历链表的临时指针变量,是用于保存下一个节点的临时指针变量,而是链表的头指针。

使用宏可以安全地遍历整个链表,从链表的第一个节点开始,一直迭代到最后一个节点。在每次迭代时,指向当前节点的指针,而指向下一个节点的指针。

该宏的安全性体现在它在遍历过程中允许对链表进行删除、插入等修改操作,而不会导致迭代器失效或发生内存访问错误。它通过在每次迭代前保存下一个节点的指针,以确保即使当前节点被删除或移动,仍然可以安全地继续迭代下一个节点。

以下是一个示例,展示了如何使用宏安全地遍历链表并删除节点

 

在上述示例中,使用宏安全地遍历了名为的双向链表,并在每次迭代中删除了当前节点。通过使用安全遍历的方式,即使删除了当前节点,仍然能够正确地获取并迭代下一个节点,而不会导致迭代器失效。

通过使用宏,可以在遍历链表的同时进行删除、插入或其他修改操作,确保遍历过程的安全性和正确性。

 

list_for_each_prev_safe宏接受三个参数:pos、n和head。其中,pos是用于迭代遍历链表的临时指针变量,n是用于保存上一个节点的临时指针变量,而head是链表的头指针。

使用list_for_each_prev_safe宏可以安全地逆向遍历整个链表,从链表的最后一个节点开始,一直迭代到第一个节点。在每次迭代时,pos指向当前节点的指针,而n指向上一个节点的指针。

该宏的安全性体现在它在遍历过程中允许对链表进行删除、插入等修改操作,而不会导致迭代器失效或发生内存访问错误。它通过在每次迭代前保存上一个节点的指针n,以确保即使当前节点被删除或移动,仍然可以安全地继续迭代上一个节点。

是一个宏定义,在 Linux 内核中用于遍历双向链表并访问链表节点的宏。

该宏的定义如下

 

宏接受三个参数:、 和 。其中, 是用于迭代遍历链表节点的指针变量, 是链表的头指针, 是链表节点在结构体中的成员名。

使用 宏可以按顺序遍历链表中的每个节点,并通过 获取节点所在结构体的指针。宏内部使用了 宏,将链表节点指针转换为包含该节点的结构体的指针。

以下是一个示例,展示了如何使用 宏遍历链表并访问节点

 

在上述示例中,使用 宏遍历了名为 的双向链表。通过 指针可以访问每个节点所在的结构体,并访问结构体中的成员(例如 )。

通过使用 宏,可以方便地遍历链表并访问节点,简化了代码的编写过程。

是一个宏定义,在 Linux 内核中用于逆向遍历双向链表并访问链表节点的宏。

该宏定义如下

 

宏接受三个参数:、 和 。其中, 是用于迭代遍历链表节点的指针变量, 是链表的头指针, 是链表节点在结构体中的成员名。

使用 宏可以逆序遍历链表中的每个节点,并通过 获取节点所在结构体的指针。宏内部使用了 宏,将链表节点指针转换为包含该节点的结构体的指针。

以下是一个示例,展示了如何使用 宏逆序遍历链表并访问节点

 

在上述示例中,使用 宏逆序遍历了名为 的双向链表。通过 指针可以访问每个节点所在的结构体,并访问结构体中的成员(例如 )。

通过使用 宏,可以方便地逆序遍历链表并访问节点,简化了代码的编写过程。

list_for_each_entry_continue 是一个宏定义,在 Linux 内核中用于在给定位置之后继续遍历双向链表并访问链表节点的宏。

 
 

list_for_each_entry_continue_reverse 是一个宏定义,在 Linux 内核中用于在给定位置之前逆向遍历双向链表并访问链表节点的宏。

 

list_for_each_entry_continue_reverse 宏接受三个参数:pos、head 和 member。其中,pos 是用于迭代遍历链表节点的指针变量,head 是链表的头指针,member 是链表节点在结构体中的成员名。

是一个宏定义,在 Linux 内核中用于从指定位置开始遍历双向链表并访问链表节点的宏。

该宏的定义如下

 

宏接受三个参数:、 和 。其中, 是用于迭代遍历链表节点的指针变量, 是链表的头指针, 是链表节点在结构体中的成员名。

使用 宏可以从指定位置开始遍历链表中的每个节点,并通过 获取节点所在结构体的指针。宏内部使用了 宏,将链表节点指针转换为包含该节点的结构体的指针。

以下是一个示例,展示了如何使用 宏从指定位置开始遍历链表并访问节点

 

在上述示例中,使用 宏从指定位置 开始遍历名为 的双向链表,并访问每个节点。

通过使用 宏,可以方便地从指定位置开始遍历链表并访问节点,简化了代码的编写过程。

是一个宏定义,在 Linux 内核中用于从指定位置之前逆向遍历双向链表并访问链表节点的宏。

该宏的定义如下

 

宏接受三个参数:、 和 。其中, 是用于迭代遍历链表节点的指针变量, 是链表的头指针, 是链表节点在结构体中的成员名。

使用 宏可以从指定位置之前逆向遍历链表中的每个节点,并通过 获取节点所在结构体的指针。宏内部使用了 宏,将链表节点指针转换为包含该节点的结构体的指针。

以下是一个示例,展示了如何使用 宏从指定位置之前逆向遍历链表并访问节点

 

在上述示例中,使用 宏从指定位置 之前开始逆向遍历名为 的双向链表,并访问每个节点。

通过使用 宏,可以方便地从指定位置之前逆向遍历链表并访问节点,简化了代码的编写过程。

是一个宏定义,在 Linux 内核中用于安全地遍历双向链表并访问链表节点的宏。

该宏的定义如下

 

宏接受四个参数:、、 和 。其中, 是用于迭代遍历链表节点的指针变量, 是一个临时指针变量, 是链表的头指针, 是链表节点在结构体中的成员名。

使用 宏可以安全地遍历链表中的每个节点,并通过 获取节点所在结构体的指针。宏内部使用了 宏,将链表节点指针转换为包含该节点的结构体的指针。

一个关键的特性是使用了临时变量 ,用于存储当前节点的下一个节点的位置,从而在遍历过程中安全地删除或添加节点。

以下是一个示例,展示了如何使用 宏安全地遍历链表并访问节点

 

在上述示例中,使用 宏安全地遍历名为 的双向链表,并访问每个节点。在遍历过程中,可以安全地删除节点,而不会影响遍历的正确性。

通过使用 宏,可以方便地安全地遍历链表并访问节点,确保在遍历过程中可以进行安全的节点操作。

是一个宏定义,在Linux内核中用于安全地继续遍历双向链表并访问链表节点的宏。

该宏的定义如下

 

宏接受四个参数:、、 和 。其中, 是用于迭代遍历链表节点的指针变量, 是一个临时指针变量, 是链表的头指针, 是链表节点在结构体中的成员名。

使用 宏可以安全地继续遍历链表中的每个节点,并通过 获取节点所在结构体的指针。宏内部使用了 宏,将链表节点指针转换为包含该节点的结构体的指针。

与 宏类似, 宏也使用了临时变量 ,用于存储当前节点的下一个节点的位置,从而在遍历过程中安全地删除或添加节点。

以下是一个示例,展示了如何使用 宏安全地继续遍历链表并访问节点

 

在上述示例中,首先使用 宏安全地遍历链表并删除节点。然后,使用 宏继续安全地遍历链表并访问节点,包括在前面遍历过程中没有被删除的节点。

通过使用 宏,可以方便地安全地继续遍历链表并访问节点,确保在遍历过程中可以进行安全的节点操作,并继续遍历链表中的剩余节点。

从当前安全点开始迭代链表,防止删除

 
 

该宏用于向后安全迭代链表,防止删除

 
 

在内核中,链表是一种常用的数据结构,用于管理和组织各种内核数据。链表的主要作用包括以下几个方面

(1)动态存储:链表提供了一种动态存储数据的方式。内核中的数据往往是动态创建和销毁的,链表能够方便地进行插入、删除和重新排序操作,以适应数据的动态变化。

(2)数据组织:链表提供了一种将多个数据元素组织在一起的方式。内核中存在各种数据结构,例如进程控制块(Process Control Block)、文件描述符表(File Descriptor Table)、网络数据结构等,链表可以将这些数据结构进行链接,形成数据的有序组织。

(3)遍历和访问:链表允许按照特定顺序遍历和访问数据。内核中的各种数据结构可能需要进行遍历和访问,链表提供了便捷的方式来遍历链表中的节点,并访问节点中的数据。

(4)插入和删除:链表支持在任意位置插入和删除节点。内核中经常需要动态地插入和删除数据,例如创建和销毁进程、打开和关闭文件等操作,链表提供了灵活的插入和删除操作,使得数据的动态管理更加高效。

(5)搜索和查找:链表可以用于搜索和查找特定的数据。内核中的某些操作需要根据条件搜索特定的数据,例如查找文件描述符、查找网络连接等,链表提供了一种有序的数据组织方式,便于进行搜索和查找。

    以上就是本篇文章【【linux kernel】linux内核数据结构分析之链表】的全部内容了,欢迎阅览 ! 文章地址:http://www.razcy.com/quote/4431.html 
     行业      资讯      企业新闻      行情      企业黄页      同类资讯      网站地图      返回首页 月落星辰移动站 http://m.razcy.com/ , 查看更多