Linux内核的list_head民用改造

2017-01-10

list_head是Linux内核中使用最广泛的双向链表,每个节点都可以为任意类型,可以作为栈或队列使用,没有读过Linux内核的同学应该是没见过如此有创意的链表得意

今天对linux内核中的list_head稍作修改,以便民用,不再是军用专属。

申明:本来很久没写代码了,没装任何IDE环境,所涉及到的代码不保证正确。今天只是蛋疼大笑

直接上代码:


list_head.h

/***************************************************************************************************
* 
*								Linux的list_head链表民用改造
*
****************************************************************************************************
*
* 文    件:list_head.h
*
* 功能描述:
*			1. 大多数情况C码农们可能对不同数据类型需要创建不同类型的链表,使得代码量增加及运行时内存
*			的消耗增加。
*			2. Linux内核中有一个叫list_head的双向链表,各种总线驱动都使用list_head进行driver与device
*			之间的匹配,然后加载相应的驱动
*			3. 由于list_head可以挂任意类型的节点,因此每个节点对应的结构体中必须包含一个list_head类型
*			的成员,无其他要求。
*
* 创建日期:2016.12.29
* 作    者:oneonce
* 版    本:v1.00.000
*
***************************************************************************************************/



#ifndef __LIST_HEAD_H__
#define __LIST_HEAD_H__




#ifdef c__plusplus
	extern "c"{
#endif


/***************************************************************************************************
使用方法:


struct test_node
{
	int value;
	list_head_t h;// 需要添加到list_head_t类型的列表节点结构体必须包含一个list_head_t成员
};

void test()
{
	list_head_t my_list;
	list_head_t *entry = NULL;
	test_node a, b, c;
	
	list_head_init(&my_list);
	
	a.value = 1;
	b.value = 2;
	c.value = 3;
	
#if 0 // 压栈操作(列表作为栈使用)
	list_push_stack(&a.h, &my_list);// a压栈
	list_push_stack(&b.h, &my_list);// b压栈
	list_push_stack(&c.h, &my_list);// c压栈
#else // 入列操作(列表作为队列使用)
	list_enqueue(&a.h, &my_list);// a入列
	list_enqueue(&b.h, &my_list);// b入列
	list_enqueue(&c.h, &my_list);// c入列
#endif

	int size = list_size(&my_list);// 列表大小

	list_for_each(entry, &my_list)
	{
		test_node *node = list_entry(entry, struct test_node, h);
		printf("node value: %d\n", node->value);
	}
	
#if 0 // 出栈操作(列表作为栈使用)
	entry = list_pop_stack(&a.h, &my_list);// a出栈
	//entry = list_pop_stack(&b.h, &my_list);// b出栈
	//entry = list_pop_stack(&c.h, &my_list);// c出栈
#else // 出列操作(列表作为队列使用)
	entry = list_dequeue(&a.h, &my_list);// a出列
	entry = list_dequeue(&b.h, &my_list);// b出列
	entry = list_dequeue(&c.h, &my_list);// c出列
#endif

	test_node *node = list_entry(entry, struct test_node, h);// 很关键。也是list_head最巧妙的地方,根据指向结构体中list_head成员的指针得到指向结构体的指针(自定义的结构体)
	printf("出栈/出列node value: %d\n", node->value);
	
	list_revese(&my_list);// 列表倒置
}

***************************************************************************************************/


#define offsetof(TYPE, MEMBER)					(((size_t)&(TYPE *)0)->MEMBER)// 得到结构体成员在结构体中的偏移量
#define container_of(ptr, type, member)			((type *)((char *)ptr - offsetof(type, member)))// 得到指向结构体指针的首地址
#define list_for_each(pos, head)				for (pos = (head)->next; pos != (head); pos = pos->next)// for循环
#define list_for_each_r(pos, head)				for (pos = (head)->prev; pos != (head); pos = pos->prev)// 反向for循环
#define list_entry(ptr, type, member)			(NULL == ptr)? NULL : container_of(ptr, type, member)// 根据‘指向结构体list_head_t成员指针’和‘结构体类型’以及结构体中‘list_head_t成员名’得到结构体首地址




typedef struct list_head
{
	struct list_head *prev;
	struct list_head *next;
} list_head_t, *plist_head_t;


typedef enum list_type
{
	TYPE_UNKNOWN = -1,// 未知类型
	TYPE_STACK,// 栈类型的列表
	TYPE_QUEUE,// 队列类型的列表
} list_type_t;




int list_head_init(list_head_t *head);// 初始化表头,使用列表前必须初始化表头
int list_push_stack(list_head_t *entry, list_head_t *head);// 作为栈使用,把entry压入到以head为表头的列表中
list_head_t *list_pop_stack(list_head_t *head);// 作为栈使用,把以head为表头的列表中的栈顶节点出栈
int list_enqueue(list_head_t *entry, list_head_t *head);// 作为队列使用,把entry入列到以head为表头的列表中
list_head_t *list_dequeue(list_head_t *head);// 作为队列使用,把以head为表头的列表中队列头的节点出列
int list_insert_before(list_head_t *entry, list_head_t *ref, list_type_t type);// 在ref节点的前面插入entry节点
int list_insert_after(list_head_t *entry, list_head_t *ref, list_type_t type);// 在ref节点的后面插入entry节点
int list_insert(list_head_t *entry, list_head_t *prev, list_head_t *next);// 在prev和next节点之间插入entry节点
list_head_t *list_delete_entry(list_head_t *entry, list_head_t *head);// 从以head为表头的列表中删除entry节点,仅仅断开节点,返回断开节点后调用者释放内存
int list_is_empty(const list_head_t *head);// 以head为表头的列表是否为空
int list_size(const list_head_t *head);// 获取以head为表头的列表的大小
list_splice_to_head(list_head_t *_new, list_head_t *head);// 把新的列表_new合并到以head为表头的列表的头部
list_splice_to_tail(list_head_t *_new, list_head_t *head);// 把新的列表_new合并到以head为表头的列表的尾部
int list_replace(list_head_t *_new, list_head_t *old);// 把列表中old节点替换为新的_new节点
int list_revese(list_head_t *head);// 把以head为表头的列表中的所有节点前后顺序倒置,倒置后仍然以head为表头





#ifdef c__plusplus
	}
#endif

#endif

list_head.c

/***************************************************************************************************
* 
*								Linux的list_head链表民用改造
*
****************************************************************************************************
*
* 文    件:list_head.c
*
* 功能描述:
*			1. 大多数情况C码农们可能对不同数据类型需要创建不同类型的链表,使得代码量增加及运行时内存
*			的消耗增加。
*			2. Linux内核中有一个叫list_head的双向链表,各种总线驱动都使用list_head进行driver与device
*			之间的匹配,然后加载相应的驱动
*			3. 由于list_head可以挂任意类型的节点,因此每个节点对应的结构体中必须包含一个list_head类型
*			的成员,无其他要求。
*
* 创建日期:2016.12.29
* 作    者:oneonce
* 版    本:v1.00.000
*
***************************************************************************************************/



#include <stdio.h>
#include "list_head.h"







#define LIST_POINT1				((void *)0x00100100)
#define LIST_POINT2				((void *)0x00200200)




typedef enum splice_mode
{
	SPLICE_UNKNOWN = -1,
	SPLICE_HEAD, // 合并列表时把新的列表合并都原有列表的表头
	SPLICE_TAIL, // 合并列表时把新的列表合并都原有列表的表尾
} splice_mode_t;




static void __list_add(list_head_t *entry, list_head_t *prev, list_head_t *next);
static void __list_del(list_head_t *entry, list_head_t *prev, list_head_t *next);
static int __list_splice(list_head_t *list, list_head_t *head, splice_mode_t mode);






/***************************************************************************************************
* 函数名:int list_head_init(list_head_t *head)
* 功能描述:初始化表头,使用列表前必须初始化表头
* 输入参数:
* 	head	:列表表头
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_head_init(list_head_t *head)
{
	if (NULL == head)
	{
		return -1;
	}

	head->prev = head;
	head->next = head;
	
	return 0;
}

/***************************************************************************************************
* 函数名:int list_push_stack(list_head_t *entry, list_head_t *head)
* 功能描述:作为栈使用,把entry压入到以head为表头的列表中
* 输入参数:
* 	entry	:待压栈节点
*	head	: 以head为表头的列表
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_push_stack(list_head_t *entry, list_head_t *head)
{
	if (NULL == entry || NULL == head)
	{
		return -1;
	}
	
	__list_add(entry, head, head->next);
	
	return 0;
}

/***************************************************************************************************
* 函数名:list_head_t *list_pop_stack(list_head_t *head)
* 功能描述:作为栈使用,把以head为表头的列表中的栈顶节点出栈
* 输入参数:
*	head	: 以head为表头的列表
* 输出参数:
*	无
* 返回值:
*	非NULL	:成功
*	NULL	:失败
***************************************************************************************************/
inline list_head_t *list_pop_stack(list_head_t *head)
{
	if (list_is_empty(head))
	{
		return NULL;
	}
	
	list_head_t *entry = head->next;
	if (head != entry)
	{
		//list_head_t *next = entry->next;
		//head->next = next;
		//next->prev = head;
		
		__list_del(entry, entry->prev, entry->next);
		
		return entry;
	}
	
	return NULL;
}

/***************************************************************************************************
* 函数名:int list_enqueue(list_head_t *entry, list_head_t *head)
* 功能描述:作为队列使用,把entry入列到以head为表头的列表中
* 输入参数:
* 	entry	:待入列节点
*	head	: 以head为表头的列表
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_enqueue(list_head_t *entry, list_head_t *head)
{
	if (NULL == entry || NULL == head)
	{
		return -1;
	}
	
	__list_add(entry, head->prev, head);
	
	return 0;
}

/***************************************************************************************************
* 函数名:list_head_t *list_dequeue(list_head_t *head)
* 功能描述:作为队列使用,把以head为表头的列表中队列头的节点出列
* 输入参数:
*	head	: 以head为表头的列表
* 输出参数:
*	无
* 返回值:
*	非NULL	:成功
*	NULL	:失败
***************************************************************************************************/
inline list_head_t *list_dequeue(list_head_t *head)
{
	return list_pop_stack(head);
}

inline void __list_add(list_head_t *entry, list_head_t *prev, list_head_t *next)
{
	next->prev = entry;
	entry->next = next;
	entry->prev = prev;
	prev->next = entry;
}

/***************************************************************************************************
* 函数名:int list_insert_before(list_head_t *entry, list_head_t *ref, list_type_t type)
* 功能描述:在ref节点的前面插入entry节点
* 输入参数:
*	entry	: 待插入节点
*	ref		: 插入点的参考节点
*	type	: 是否以栈还是队列方式进行操作
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_insert_before(list_head_t *entry, list_head_t *ref, list_type_t type)
{
	if (NULL == entry || NULL == ref || TYPE_UNKNOWN == type)
	{
		return -1;
	}
	
	if (ref->prev == ref->next && ref == ref->prev)// 空列表
	{
		return -1;
	}
	
	if (TYPE_STACK == type)// 栈
	{
		__list_add(entry, ref, ref->next);
	}
	else if (TYPE_QUEUE == type)// 队列
	{
		__list_add(entry, ref->prev, ref);
	}
	
	return 0;
}

/***************************************************************************************************
* 函数名:int list_insert_after(list_head_t *entry, list_head_t *ref, list_type_t type)
* 功能描述:在ref节点的后面插入entry节点
* 输入参数:
*	entry	: 待插入节点
*	ref		: 插入点的参考节点
*	type	: 是否以栈还是队列方式进行操作
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_insert_after(list_head_t *entry, list_head_t *ref, list_type_t type)
{
	if (NULL == entry || NULL == ref || TYPE_UNKNOWN == type)
	{
		return -1;
	}
	
	if (ref->prev == ref->next && ref == ref->prev)// 空列表
	{
		return -1;
	}
	
	if (TYPE_STACK == type)// 栈
	{
		__list_add(entry, ref->prev, ref);
	}
	else if (TYPE_QUEUE == type)// 队列
	{
		__list_add(entry, ref, ref->next);
	}
	
	return 0;
}

/***************************************************************************************************
* 函数名:int list_insert(list_head_t *entry, list_head_t *prev, list_head_t *next)
* 功能描述:在prev和next节点之间插入entry节点
* 输入参数:
*	entry	: 待插入节点
*	prev	: entry前节点
*	next	: entry后节点
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_insert(list_head_t *entry, list_head_t *prev, list_head_t *next)
{
	if (NULL == entry || NULL == prev || NULL == next)
	{
		return -1;
	}
	
	if ((prev == next) || // 空列表
		(prev->prev == prev->next && prev->prev == next))// 列表只有1个节点
	{
		return -1;// 无节点或1个节点没法插入,返回失败
	}
	
	if (prev->next == next)
	{
		__list_add(entry, prev, next);
	}
	else if (prev->prev == next)// 调用者把插入点前后传错了
	{
		__list_add(entry, next, prev);
	}
	else // 前后节点不相邻
	{
		return -1;
	}
	
	return 0;
}

/***************************************************************************************************
* 函数名:list_head_t *list_delete_entry(list_head_t *entry, list_head_t *head)
* 功能描述:从以head为表头的列表中删除entry节点,仅仅断开节点,返回断开节点后调用者释放内存
* 输入参数:
*	entry	: 待插入节点
*	head	: 列表表头
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline list_head_t *list_delete_entry(list_head_t *entry, list_head_t *head)
{
	if (list_is_empty(head) || NULL == entry || head == entry)
	{
		return NULL;
	}
	
	__list_del(entry, entry->prev, entry->next);

	return entry;
}

inline void __list_del(list_head_t *entry, list_head_t *prev, list_head_t *next)
{
	next->prev = prev;
	prev->next = next;
	
#if 0// 编译段错误(内核中)?
	entry->prev = LIST_POINT1;
	entry->next = LIST_POINT2;
#else
	entry->prev = NULL;
	entry->next = NULL;
#endif
}

/***************************************************************************************************
* 函数名:int list_is_empty(const list_head_t *head)
* 功能描述:以head为表头的列表是否为空
* 输入参数:
*	head	: 列表表头
* 输出参数:
*	无
* 返回值:
*	1		:空
*	0		:非空
***************************************************************************************************/
inline int list_is_empty(const list_head_t *head)
{
	if (NULL == head)
	{
		return 1;
	}
	
	return head->next == head;
}

/***************************************************************************************************
* 函数名:int list_size(const list_head_t *head)
* 功能描述:获取以head为表头的列表的大小
* 输入参数:
*	head	: 列表表头
* 输出参数:
*	无
* 返回值:
*	>0		:非空
*	0		:空
***************************************************************************************************/
inline int list_size(const list_head_t *head)
{
	int size = 0;
	list_head_t *entry = NULL;
	
	if (NULL == head)
	{
		return 0;
	}
	
	list_for_each(entry, head)
	{
		size++;
	}
	
	return size;
}

/***************************************************************************************************
* 函数名:int list_splice_to_head(list_head_t *_new, list_head_t *head)
* 功能描述:把新的列表_new合并到以head为表头的列表的头部
* 输入参数:
*	_new	: 待合并列表
*	head	: 原有列表
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_splice_to_head(list_head_t *_new, list_head_t *head)
{
	return __list_splice(_new, head, SPLICE_HEAD);
}

/***************************************************************************************************
* 函数名:int list_splice_to_tail(list_head_t *_new, list_head_t *head)
* 功能描述:把新的列表_new合并到以head为表头的列表的尾部
* 输入参数:
*	_new	: 待合并列表
*	head	: 原有列表
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_splice_to_tail(list_head_t *_new, list_head_t *head)
{
	return __list_splice(_new, head, SPLICE_TAIL);
}

inline int __list_splice(list_head_t *list, list_head_t *head, splice_mode_t mode)
{
	list_head_t *first = NULL;
	list_head_t *last = NULL;
	
	if (NULL == list || list_is_empty(list) || list_is_empty(head) || SPLICE_UNKNOWN == mode)
	{
		return -1;
	}
	
	first = list->next;
	last = list->prev;
	
	if (SPLICE_HEAD == mode)
	{
		list_head_t *at = head->next;
		
		first->prev = head;
		head->next = first;
		
		last->next = at;
		at->prev = last;
	}
	else if (SPLICE_TAIL == mode)
	{
		list_head_t *at = head->prev;
		
		first->prev = at;
		at->next = first;
		
		last->next = head;
		head->prev = last;
	}
	
	return 0;
}

/***************************************************************************************************
* 函数名:int list_replace(list_head_t *_new, list_head_t *old)
* 功能描述:把列表中old节点替换为新的_new节点
* 输入参数:
*	_new	: 待替换节点
*	old		: 被替换节点
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_replace(list_head_t *_new, list_head_t *old)
{
	if (NULL == _new || NULL == old)
	{
		return -1;
	}
	_new->next = old->next;
	_new->next->prev = _new;
	
	_new->prev = old->prev;
	_new->prev->next = _new;
}

/***************************************************************************************************
* 函数名:int list_revese(list_head_t *head)
* 功能描述:把以head为表头的列表中的所有节点前后顺序倒置,倒置后仍然以head为表头
* 输入参数:
*	head	: 表头
* 输出参数:
*	无
* 返回值:
*	0		:成功
*	-1		:失败
***************************************************************************************************/
inline int list_revese(list_head_t *head)
{
	list_head_t *first = NULL;
	list_head_t *entry = NULL;
	
	if (NULL == head)
	{
		return -1;
	}
	
	if (list_is_empty(head)
	{
		return -1;
	}
	
	first = head->next;
	
	while (head != first->next)
	{
		entry = first->next;
		
		first->next = entry->next;
		entry->next->prev = first;
		
		head->next->prev = entry;
		entry->next = head->next;
		
		head->next = entry;
		entry->prev = head;
	}
	
	return 0;
}



注明:本文章属于转载,仅供行业人员学习交流使用,文章版权属于原创作者,在此向原创者致敬,感谢原创作者为大家学习交流提供精品内容。

站方声明:IThao123是为广大互联网从业者免费提供学习交流的平台,如果侵犯了原创著作权,请联系站方删除,给你带来不便,深表歉意。

顶部