linux内核链表

一、链表代码

下面链表代码并不完整,完整代码可以到github上linux内核下载,网址linux/include at master · torvalds/linux · GitHub,在linux目录路径为 linux-master\include\linux\list.h

注:下面链表代码只能在linux环境运行,windows运行不了

复制代码
/*
 * Copy from linux/list.h
 */

#ifndef _GCP_MISC_LIST_H_
#define _GCP_MISC_LIST_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stddef.h>

#define LIST_POISON1 NULL
#define LIST_POISON2 NULL

#define container_of(ptr, type, member)                                                            \
    ({                                                                                             \
        const typeof(((type *)0)->member) *__mptr = (ptr);                                         \
        (type *)((char *)__mptr - offsetof(type, member));                                         \
    })

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

#define LIST_HEAD_INIT(name)                                                                       \
    { &(name), &(name) }

#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

/**
 * init_list_head - Initialize a list_head structure
 * @list: list_head structure to be initialized.
 *
 * Initializes the list_head to point to itself.  If it is a list header,
 * the result is an empty list.
 */
static inline void init_list_head(struct list_head *list) {
    list->prev = list;
    list->next = list;
}

static inline void __list_add(struct list_head *new_entry, struct list_head *prev,
                              struct list_head *next) {
    next->prev      = new_entry;
    new_entry->next = next;
    new_entry->prev = prev;
    prev->next      = new_entry;
}

/**
 * list_add - add a new_entry entry after the specified head
 * @new_entry: new_entry entry to be added
 * @head: list head to add it after
 *
 * Insert a new_entry entry after the specified head.
 * This is good for implementing stacks.
 */
static inline void list_add(struct list_head *new_entry, struct list_head *head) {
    __list_add(new_entry, head, head->next);
}

/**
 * list_add_tail - add a new_entry entry before the specified head
 * @new_entry: new_entry entry to be added
 * @head: list head to add it before
 *
 * Insert a new_entry entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new_entry, struct list_head *head) {
    __list_add(new_entry, head->prev, head);
}

static inline void __list_del(struct list_head *prev, struct list_head *next) {
    prev->next = next;
    next->prev = prev;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty() on entry does not return true after this, the entry is
 * in an undefined state.
 */
static inline void list_del(struct list_head *entry) {
    __list_del(entry->prev, entry->next);
    entry->next = LIST_POISON1;
    entry->prev = LIST_POISON2;
}

static inline void __list_splice(struct list_head *list, struct list_head *head) {
    struct list_head *first = list->next;
    struct list_head *last  = list->prev;
    struct list_head *at    = head->next;

    first->prev = head;
    head->next  = first;

    last->next = at;
    at->prev   = last;
}
/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline int list_empty(const struct list_head *head) {
    return head->next == head;
}
/**
 * list_splice - join two lists
 * @list: the new_entry list to add.
 * @head: the place to add it in the first list.
 */
static inline void list_splice(struct list_head *list, struct list_head *head) {
    if (!list_empty(list))
        __list_splice(list, head);
}
/**
 * list_replace - replace old entry by new_entry one
 * @old : the element to be replaced
 * @new_entry : the new_entry element to insert
 *
 * If @old was empty, it will be overwritten.
 */
static inline void list_replace(struct list_head *old, struct list_head *new_entry) {
    new_entry->next       = old->next;
    new_entry->next->prev = new_entry;
    new_entry->prev       = old->prev;
    new_entry->prev->next = new_entry;
}

/**
 * list_replace_init - replace old entry by new one and initialize the old one
 * @old : the element to be replaced
 * @new : the new element to insert
 *
 * If @old was empty, it will be overwritten.
 */
static inline void list_replace_init(struct list_head *old, struct list_head *new_entry) {
    list_replace(old, new_entry);
    init_list_head(old);
}
/**
 * list_move - delete from one list and add as another's head
 * @list: the entry to move
 * @head: the head that will precede our entry
 */
static inline void list_move(struct list_head *list, struct list_head *head) {
    __list_del(list->prev, list->next);
    list_add(list, head);
}

/**
 * list_move_tail - delete from one list and add as another's tail
 * @list: the entry to move
 * @head: the head that will follow our entry
 */
static inline void list_move_tail(struct list_head *list, struct list_head *head) {
    __list_del(list->prev, list->next);
    list_add_tail(list, head);
}

/**
 * list_entry - get the struct for this entry
 * @ptr:	the &struct list_head pointer.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_head within the struct.
 */
#define list_entry(ptr, type, member) container_of(ptr, type, member)

/**
 * list_first_entry - get the first element from a list
 * @ptr:	the list head to take the element from.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_head within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define list_first_entry(ptr, type, member) list_entry((ptr)->next, type, member)

/**
 * list_last_entry - get the last element from a list
 * @ptr:	the list head to take the element from.
 * @type:	the type of the struct this is embedded in.
 * @member:	the name of the list_head within the struct.
 *
 * Note, that list is expected to be not empty.
 */
#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member)

/**
 * list_for_each	-	iterate over a list
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 */
#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)
/**
 * list_for_each_entry	-	iterate over list of given type
 * @pos:	the type * to use as a loop cursor.
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry(pos, head, member)                                                     \
    for (pos = list_entry((head)->next, typeof(*pos), member); &pos->member != (head);             \
         pos = list_entry(pos->member.next, typeof(*pos), member))
/**
 * list_for_each_prev	-	iterate over a list backwards
 * @pos:	the &struct list_head to use as a loop cursor.
 * @head:	the head for your list.
 */
#define list_for_each_prev(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev)

/**
 * list_for_each_safe - iterate over a list safe against removal of list entry
 * @pos:	the &struct list_head to use as a loop cursor.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 */
#define list_for_each_safe(pos, n, head)                                                           \
    for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next)

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:	the type * to use as a loop cursor.
 * @n:		another type * to use as temporary storage
 * @head:	the head for your list.
 * @member:	the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)                                             \
    for (pos                         = list_entry((head)->next, typeof(*pos), member),             \
        n                            = list_entry(pos->member.next, typeof(*pos), member);         \
         &pos->member != (head); pos = n, n = list_entry(n->member.next, typeof(*n), member))

#ifdef __cplusplus
}
#endif

#endif /* _GCP_MISC_LIST_H_ */

二、简单演示

复制代码
#include <stdio.h>
#include <stdlib.h>
#include "list.h"

typedef struct node{
    int id;
    struct list_head list
} Node;

int main() {
    struct list_head list_node_head;

    init_list_head(&list_node_head);               // 初始化链表

    for(int i = 0; i < 10; i ++){
        Node* newNode = (Node*)malloc(sizeof(Node));
        newNode->id = i;
        list_add(&newNode->list, &list_node_head); // 添加节点
    }

    Node* currentNode, *nextNode;                  // 临时变量
    list_for_each_entry(currentNode, &list_node_head, list){ // 遍历节点
        printf("Node ID: %d\n", currentNode->id); 
    }

    list_for_each_entry_safe(currentNode, nextNode, &list_node_head, list) { // 释放内存
        list_del(&currentNode->list);
        free(currentNode);
    }

    return 0;
}

三、详细解释

linux内核链表是其他结构体中来包含struct list_head来实现的,巧妙的运用了宏和链表元素list_head在结构体内的位置关系构。

1.该宏通过struct list_head在结构体的相对位置来确定节点头位置。

比如这样的结构体

struct node{

int id;

struct list_head list

} ; list_node_head->list,通过list与id相对位置关系来得出struct node的地址,最后 获取id的值。

复制代码
#define container_of(ptr, type, member)                                                            \
    ({                                                                                             \
        const typeof(((type *)0)->member) *__mptr = (ptr);                                         \
        (type *)((char *)__mptr - offsetof(type, member));                                         \
    })

2.链表初始化,两种初始化方式

复制代码
#define LIST_HEAD_INIT(name)                                                                       \
    { &(name), &(name) }

#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)

static inline void init_list_head(struct list_head *list) {
    list->prev = list;
    list->next = list;
}

3.遍历

复制代码
/**
* @pos 是临时指针,记录遍历节点的,类型:你定义的结构体,如举例的 Node 结构体
* @head 是头指针,类型:struct list_head
* @member 是在结构体中,struct list_head 的名称,如举例中Node结构体的list
*/

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


list_for_each_entry(currentNode, &list_node_head, list)

内容不过多说,大家自己看英文注释,都很清楚。

相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
Yana.nice2 小时前
Linux 只保留 30 天内日志(find命令删除日志文件)
linux·运维·chrome
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海3 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
DFT计算杂谈6 小时前
无 Root 权限在 Tesla K80 零门槛部署 DeepSeek 大模型
linux·服务器·网络·数据库·机器学习
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai7 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang