linux内核list_splice函数 (拼接两个链表)

原文有错误,已经修改。

/*********************************
拼接两个链表:
1.如果新增的链表只有一个链表头就不做任何处理(因为链表头不包含数据)
2. (head 2 3) + (add 5 6)    
  ==> (head 5 6 2 3)  //抛弃链表头add
*********************************/
/* Join two lists. */
static inline void list_splice (list_t *add, list_t *head)
{
 	/* Do nothing if the list which gets added is empty. */
	if (add != add->next)
	{
		add->next->prev = head;       // 5的上一项是head
		add->prev->next = head->next; // 6的下一项是2
		head->next->prev = add->prev; // 2的上一项是6
		head->next = add->next;       // head的下一项是5
	}
}
/*注意:所有使用list_head结构体的函数使用前必须对参数中list_head结构体初始化!曾经因为list_splice()中head没有初始化导致一进到这个函数就异常重启! */
#include "list.h"
#include <stdio.h>
 
static LIST_HEAD (head);	
static LIST_HEAD (head2);	
typedef struct T
{	char *name;
	list_t member;	// pre, next
}type;
 
int main(int argc, char **argv)
{
	type a,b,c,d;
	list_t *ptr;	// 节点指针
	type *t;
	list_t *tmp = NULL;
	
	a.name = "a";
	b.name = "b";
	c.name = "c";
	d.name = "d";
	
	list_add(&a.member, &head); // 紧挨着链表头插入新节点
	list_add(&b.member, &head); // 紧挨着链表头插入新节点
	
	list_add(&c.member, &head2); // 紧挨着链表头插入新节点
	list_add(&d.member, &head2); // 紧挨着链表头插入新节点
 
	list_splice(&head2, &head);
#if 0
	//list_for_each_prev(ptr, &head)  直接就死机了 有删除必须加safe
	list_for_each_prev_safe(ptr, tmp, &head)
	{	t = list_entry(ptr, type, member);
		printf("%s\n", t->name);
		list_del(ptr);
	}
#endif
	/* 结果:
	book@gui_hua_shu:~/test$ ./a.out
	a
	b
	c
	d
*/
	
#if 1	
	//list_for_each(ptr, &head)  直接就死机了 有删除必须加safe
	list_for_each_safe(ptr, tmp, &head)
	{	t = list_entry(ptr, type, member);
		printf("%s\n", t->name);
		list_del(ptr);
	}
#endif
	/* 结果:
	book@gui_hua_shu:~/test$ ./a.out
	d
	c
	b
	a
*/
	return 0;
}
发布了39 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/wanggong_1991/article/details/100539705
今日推荐