奋斗的伙计

每天进步一点点

list_head使用

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




阅读更多
文章标签: 内核 源码 list_head
个人分类: linux使用
上一篇python实现文本分析并执行linux命令
下一篇内核态和用户态通讯知识收集
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭