关闭

list_head使用

标签: 内核源码list_head
181人阅读 评论(0) 收藏 举报
分类:

list_head在内核中的实现:

list.h文件源码

#ifndef _LIST_H
#define _LIST_H

#define _INLINE_ static inline

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

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

//定义并初始化头结点head
#define LIST_HEAD(name)\
    struct list_head name = LIST_HEAD_INIT(name)

//初始化头结点ptr,因此需要首先定义ptr
#define INIT_LIST_HEAD(ptr)do{\
    (ptr)->next = (ptr);\
	(ptr)->prev = (ptr);\
}while (0)

_INLINE_ void __list_add(struct list_head *add,
        struct list_head *prev,
        struct list_head *next)
{
    next->prev = add;
    add->next = next;
    add->prev = prev;
    prev->next = add;
}

_INLINE_ void list_add(struct list_head *add, struct list_head *head)//每次添加节点到head之后,始终都是添加到头结点之后
{
    __list_add(add, head, head->next);
}

_INLINE_ void list_add_tail(struct list_head *add, struct list_head *head)//每次添加节点都是头结点之前,由于是循环链表,就是说添加到链表尾部
{
    __list_add(add, head->prev, head);
}

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

_INLINE_ void list_del(struct list_head *entry)//删除节点
{
    __list_del(entry->prev, entry->next);
}

_INLINE_ void list_del_init(struct list_head *entry)
//删除节点,并初始化被删除的结点(也就是使被删除的结点的prev和next都指向自己)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}

_INLINE_ int list_empty(struct list_head *head)//判断链表是否为空
{
    return head->next == head;
}

_INLINE_ void list_splice(struct list_head *list, struct list_head *head)
//通过两个链表的head,进行连接
{
    struct list_head *first = list->next;

    if (first != list) {
        struct list_head *last = list->prev;
        struct list_head *at = head->next;

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

        last->next = at;
        at->prev = last;
    }
}

#define list_entry(ptr, type, member) \
    ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
                                  
//遍历链表,此时删除节点的操作可能会出错
#define list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next) //新代码中出现prefetch() 可以不考虑,用于预取以提高遍历速度

//遍历链表,可以同时有删除节点的操作
#define list_for_each_safe(pos, pnext, head) \
    for (pos = (head)->next, pnext = pos->next; pos != (head); \
            pos = pnext, pnext = pos->next)

#undef _INLINE_
#endif

使用实例:

use_list.c文件

#include"list.h"
#include<stdio.h>
#include<stdlib.h>

typedef struct node{
    int data;
    struct list_head list;
}node;

void main(){
    struct list_head ll, *plist;
    struct node *n;
    INIT_LIST_HEAD(&ll);

    for(int i=0; i<5; i++){
	n=(struct node *)malloc(sizeof(struct node));
        n->data=i;
	list_add_tail(&n->list, &ll);
    }

	list_for_each(plist, &ll){
		struct node *pnode=list_entry(plist, struct node, list);
		printf("data=%d\n", pnode->data);
	}
	
	if(!list_empty(&ll)){
		struct list_head *ptr=ll.next;
		list_del_init(ptr);
		n=list_entry(ptr, struct node, list);
		printf("n->data=%d\n", n->data);
	}

	printf("after remove the first node\n");	
	list_for_each(plist, &ll){
		struct node *pnode=list_entry(plist, struct node, list);
		printf("data=%d\n", pnode->data);
	}
	
	printf("list's offset=%d\n", (unsigned long)(&((struct node *)0)->list));
}

执行结果:

data=0
data=1
data=2
data=3
data=4
n->data=0
after remove the first node
data=1
data=2
data=3
data=4




0
1

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:67098次
    • 积分:1504
    • 等级:
    • 排名:千里之外
    • 原创:80篇
    • 转载:50篇
    • 译文:0篇
    • 评论:0条