学习笔记:数据结构(三)内核链表

        linux内核链表在/usr/src/linux-headers-xxx/include/linux/list.h中可以看到,其中xxx为内核版本号。我们可以采用内核链表的方式实现我们自己的数据结构。

内核链表节点定义的结构体中只包含了指针域,

struct list_head {
    struct list_head *next, *prev;
};   
        那么数据放在哪里呢?实际上内核链表是通过两层结构体的方式实现的,大结构体里面包含数据域和一个小结构体,该小结构体也就是上面的节点,链表通过小结构体联系起来,然后访问数据时通过container_of宏从小结构体转向大结构体。
  #define offset_of(type, member) \
      ((size_t)(&(((type *)0)->member)))
  
  #define container_of(ptr, type, member) \
      (type *)((size_t)(ptr) - offset_of(type, member))
  
         然后内核链表的实现采用了内联函数提高效率,相对于普通双链表,内核链表多了一步大小结构体转换的过程,其他的都差不多。下面是简易的lish.h
#pragma once

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

#define LIST_HEAD_INIT(head) \
	struct list_head (head) = {&head, &head}

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

static inline void __list_add(struct list_head *new, struct list_head *Prev, struct list_head *Next)
{
	new->next = Next;
	new->prev = Prev;

	Prev->next = new;
	Next->prev = new;
}

static inline void list_add(struct list_head *new, struct list_head *head)
{
	__list_add(new, head, head->next);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
	__list_add(new, head->prev, head);
}

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

static inline void node_del_init(struct list_head *node)
{
	node_del(node);
	list_head_init(node);
}


#define list_for_each(cur, head) \
	for ((cur) = (head)->next; (cur) != (head); (cur) = (cur)->next)

#define offset_of(type, member) \
	((size_t)(&(((type *)0)->member)))

#define container_of(ptr, type, member) \
	(type *)((size_t)(ptr) - offset_of(type, member))

#define  list_for_each_reverse(cur, head)	\
	for (cur = (head)->prev; cur != (head); cur = (cur)->prev)


#define  list_for_each_continue(cur, head)	\
	for (cur = (cur)->next; cur != (head); cur = (cur)->next)

#define  list_for_each_from(cur, head)	\
	for ( ; cur != (head); cur = (cur)->next)

/*直接遍历大结构体(宿主结构)*/
#define  list_for_each_entry(pos, head, member)	\
	for (pos = container_of((head)->next, typeof(*pos), member); &(pos)->member != head; \
	pos = container_of((pos)->member.next, typeof(*pos), member))
简单的测试
#include <stdio.h>
#include "list.h"

struct data_info {
	char *name;
	int age;
	struct list_head list;
};

int main(void)
{
	LIST_HEAD_INIT(head);
	struct data_info s[] = {
		{"mary", 25},
		{"candy", 18},
		{"jack", 24},
	};

	int i = 0;
	for (; i < sizeof(s) / sizeof(s[0]); i++) {
		list_add(&s[i].list, &head);
	}

	struct list_head *cur = NULL;
	struct data_info *pa = NULL;
	list_for_each(cur, &head) {
		pa = container_of(cur, struct data_info, list);
		printf("%s %d\n", pa->name, pa->age);
	}
	

	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值