博客
关于我
linux 获取链表节点数,LINUX基础-list链表
阅读量:792 次
发布时间:2023-02-02

本文共 1768 字,大约阅读时间需要 5 分钟。

linux链表

在研究linux内核或基于linux的代码时,我们常会遇到LIST_HEAD、INIT_LIST_HEAD等宏定义,以及list_for_each、list_entry等函数。本文将介绍这些常用宏定义和函数的意义。

struct list_head

在linux中,链表采用双向循环链表结构,定义如下:

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

需要注意的是,链表节点中并不存储数据域。与linux内核中的KObjetc类似,链表节点是嵌入在数据结构中的。这类结构在内核中较为普遍,主要用于链表操作的一种轻量级实现方式。

初始化链表

初始化一个链表节点需要使其自身的prev和next指针都指向自己。有两种常见方法:

  • LIST_HEAD(name);
  • 跟define 宏:

    #define INIT_LIST_HEAD(name) { &(name), &(name) }

    或者直接声明变量:

    struct list_head name = INIT_LIST_HEAD(name);

    这种初始化方式让节点自身环环相扣,成为一个自己的循环链表。

    1. INIT_LIST_HEAD(ptr);
    2. 这是一个宏定义,展开为:

      do {(ptr->next) = (ptr);(ptr->prev) = (ptr);} while (0);

      前提是ptr必须先申明为struct list_head类型。这两种方式在功能上没有区别,只在使用方式上有细微差别。

      链表遍历

    3. list_for_each
    4. 定义:

      #define list_for_each(pos, head)for (pos = (head)->next; prefetch(pos->next), pos != (head); pos = pos->next)

      __list_for_each

      #define __list_for_each(pos, head)for (pos = (head)->next; pos != (head); pos = pos->next)

      两者的区别在于是否带有prefetch。前者为了提高遍历效率进行预取操作,而后者则是简单的遍历。有时为了发挥性能优势,我们需要使用带有prefetch的版本。

      1. list_for_each_safe
      2. for (pos = (head)->next, n = pos->next; pos != head; pos = n, n = pos->next)

        这种遍历方式不同于list_for_each,主要是为了在遍历过程中能够安全地删除节点。list_for_each不能在循环体内删除节点,而list_for_entry则可能导致死循环或panic错误。因而在需要删除的场合,应该使用list_for_each_safe。

        list_entry函数

        list_entry(pos, type, member)

        该函数用于根据链表指针找到包含该指针的数据结构体。它实际上就是container_of函数的另一种表达方式。container_of函数通常用于 Shoblemaker结构体与其链表指针之间的转换。

        list_for_each_entry

        这个宏定义的作用是将list_for_each_entry和list_entry结合起来,以便更方便地同时获取链表节点和数据结构体。它的进一步扩展:

        #define list_for_each_entry(pos, head, member)for (pos = list_entry( (head)->next, typeof(*pos), member );prefetch(pos->member->next), &pos->member != head;pos = list_entry(pos->member->next, typeof(*pos), member))

        这个递归式的定义方式在语言实现上有些特殊表现,需要仔细理解其对->符号的处理。

        总之,理解这些链表处理宏定义和函数,是掌握linux内核链表操作的重要第一步。熟练掌握这些技巧在实际编写代码时能够发挥重要作用。

    转载地址:http://newfk.baihongyu.com/

    你可能感兴趣的文章
    Linux 系统备份与恢复详解
    查看>>
    Linux 系统安装 Mongodb 数据库
    查看>>
    Linux 系统安装MySQL
    查看>>
    Linux 系统安装配置PHP服务(源码安装)
    查看>>
    Linux 系统快键键汇总
    查看>>
    Linux 系统性能调优技巧
    查看>>
    Linux 系统时间管理与关机重启命令
    查看>>
    Linux 系统时间详解
    查看>>
    linux 系统服务管理
    查看>>
    Linux 系统查看代理,关闭代理
    查看>>
    linux 系统的ssh服务
    查看>>
    Linux 系统的用户和组详解_【all】
    查看>>
    Linux 系统监控工具大全:从命令行到图形化,全面掌握系统性能监控
    查看>>
    Linux 系统维护笔记(一)
    查看>>
    Linux 系统进程管理
    查看>>
    Linux 终端多路复用神器 Tmux 3.5 发布!支持扩展键和新功能
    查看>>
    linux 网络协议分析---3
    查看>>
    linux 网络和流量监控
    查看>>
    Linux 网络扫描工具:nmap,涨知识的时间到了!
    查看>>
    Linux 网络排查必备:轻松找出进程占用的端口号
    查看>>