<5> 紫光展锐[ENGPC] Linux基础知识之内核链表简单使用例程

学过数据结构之后,就会知道,链表是一种常用的管理数据的方式,在操作系统当中最为常见,链表大概有以下几种:

1).单向非循环链表
2).单向循环链表
3).双向非循环链表
4).双向循环链表
5).内核链表

其中个人认为越往下的链表越高级,当然,高级不一定就适用,有些地方就是需要一个简单的链表,然后可以做到少消耗资源,比如通知链,就用的是单向链表,在实时操作系统中,比如UCOS里则用的是双向循环链表,有的时候会和哈希算法一起组成哈希链表来管理多任务,UCOS的源代码是开源的,代码写的很漂亮,想学好C语言,可以先看看UCOS的代码,里面有很多编程思想都是可以借鉴的,我以前做项目遇到的一些困难,上面都能提供一个比较好的借鉴解决方式.

好了回到主题,我们本次主要说的是内核链表,它比其它几种链表的架构思想要更好一些,主要是链表和数据是分离的,且具备双向循环链表的所有特征,可以说是青出于蓝,而胜于蓝吧.在EngPC中就用到了内核链表, 关于内核链表的讲解机制,请参考其他人的博客或者相关书籍,我这里直接就以编程的方式简单使用一下内核链表,主要是可以掌握一个基础.

本次通过做一个下面的任务,让大家认识内核链表的使用方法:

用内核链表实顺序递增存储若干自然数,比如输入一个整数10,则建立一个内核链表,里面的每个节点分别存放1,2,3,4,5,6,7,8,9,10,然后通过某些操作,将其重新排列成1,3,5,7,9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来

下面是主文件代码(myapp.c):

/*
 * 用内核链表实顺序递增存储若干自然数,比如输入一个整数10,
 * 则建立一个内核链表,里面的每个节点分别存放1,2,3,4,5,
 * 6,7,8,9,10,然后通过某些操作,将其重新排列成1,3,5,7,
 * 9,10,8,6,4,2,即奇数升序偶数降序,并在屏幕上打印出来。
 */


#include "kernellist.h"

void doublelist_sort(double_pnode h);
int main(void)
{
	double_pnode h;

	doublelist_init(&h);
	doublelist_create(h);
	doublelist_sort(h);
	return 0;
}

void doublelist_sort(double_pnode h)
{
	double_pnode p,t;

	p = list_entry(h->list.prev,double_node,list);
	while(p != h){
		if(p->data % 2 == 1){  //奇数
			p = list_entry(p->list.prev,double_node,list);
		}else{  //偶数
			t = p;
			p = list_entry(p->list.prev,double_node,list);

			list_move_tail(&t->list,&h->list);
			doublelist_show(h);
		}
	}
}

然后是任务函数处理代码(kernellist.c):

#include "kernellist.h"

//初始化
void doublelist_init(double_pnode * H)
{
	*H = (double_pnode)malloc(sizeof(double_node));
	if(NULL == *H){
		perror("malloc");
		exit(1);
	}
	INIT_LIST_HEAD(&(*H)->list);
}



//遍历
void doublelist_show(double_pnode h)
{
	double_pnode p;
	list_for_each_entry(p,&h->list,list)
		printf("%d\t",p->data);
	printf("\n");
}

void doublelist_create(double_pnode h)
{
	int n,i;
	double_pnode new;

	printf("请输入内核链表长度:");
	scanf("%d",&n);
	for(i = 0; i < n; i++){
		new = (double_pnode)malloc(sizeof(double_node));
		if(NULL == new){
			perror("malloc");
			exit(1);
		}
		printf("请输入数据:");
		scanf("%d",&new->data);
		list_add_tail(&new->list,&h->list);
		doublelist_show(h);
	}
}

然后是任务函数头文件(kernellist.h):

#ifndef __KERNELLIST_H
#define __KERNELLIST_H

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#include "eng_list.h"


typedef int datatype;

typedef struct doublenode{
	datatype data;
	struct list_head list;   //list为结构体变量,不能定义成指针
}double_node,*double_pnode;


//初始化
extern void doublelist_init(double_pnode * H);
//在h指向的结点后插入新结点new
extern void doublelist_insert(double_pnode h,double_pnode new);
//在h指向的结点前插入新结点new
extern void doublelist_insert_tail(double_pnode h,double_pnode new);
//删除当前结点p
extern void doublelist_del(double_pnode p);
//判断是否为空
extern bool doublelist_isempty(double_pnode h);
//遍历
extern  void doublelist_show(double_pnode h);
extern void doublelist_create(double_pnode h);


#endif

然后就是内核链表的一些相关操作的头文件(eng_list.h):

#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H


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

#define LIST_POISON1  ((void *) 0x00100100 + 0)
#define LIST_POISON2  ((void *) 0x00200200 + 0)

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})



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

#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

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

#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next)
{
	next->prev = new;
	new->next = next;
	new->prev = prev;
	prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
			      struct list_head *prev,
			      struct list_head *next);
#endif

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 __list_del(struct list_head * prev, struct list_head * next)
{
	next->prev = prev;
	prev->next = next;
}

#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
}

static inline void list_del(struct list_head *entry)
{
	__list_del(entry->prev, entry->next);
	entry->next = LIST_POISON1;
	entry->prev = LIST_POISON2;
}
#else
extern void __list_del_entry(struct list_head *entry);
extern void list_del(struct list_head *entry);
#endif

static inline void list_replace(struct list_head *old,
				struct list_head *new)
{
	new->next = old->next;
	new->next->prev = new;
	new->prev = old->prev;
	new->prev->next = new;
}

static inline void list_replace_init(struct list_head *old,
					struct list_head *new)
{
	list_replace(old, new);
	INIT_LIST_HEAD(old);
}

static inline void list_del_init(struct list_head *entry)
{
	__list_del_entry(entry);
	INIT_LIST_HEAD(entry);
}

static inline void list_move(struct list_head *list, struct list_head *head)
{
	__list_del_entry(list);
	list_add(list, head);
}

static inline void list_move_tail(struct list_head *list,
				  struct list_head *head)
{
	__list_del_entry(list);
	list_add_tail(list, head);
}

static inline int list_is_last(const struct list_head *list,
				const struct list_head *head)
{
	return list->next == head;
}

static inline int list_empty(const struct list_head *head)
{
	return head->next == head;
}

static inline int list_empty_careful(const struct list_head *head)
{
	struct list_head *next = head->next;
	return (next == head) && (next == head->prev);
}

static inline void list_rotate_left(struct list_head *head)
{
	struct list_head *first;

	if (!list_empty(head)) {
		first = head->next;
		list_move_tail(first, head);
	}
}

static inline int list_is_singular(const struct list_head *head)
{
	return !list_empty(head) && (head->next == head->prev);
}

static inline void __list_cut_position(struct list_head *list,
		struct list_head *head, struct list_head *entry)
{
	struct list_head *new_first = entry->next;
	list->next = head->next;
	list->next->prev = list;
	list->prev = entry;
	entry->next = list;
	head->next = new_first;
	new_first->prev = head;
}

static inline void list_cut_position(struct list_head *list,
		struct list_head *head, struct list_head *entry)
{
	if (list_empty(head))
		return;
	if (list_is_singular(head) &&
		(head->next != entry && head != entry))
		return;
	if (entry == head)
		INIT_LIST_HEAD(list);
	else
		__list_cut_position(list, head, entry);
}

static inline void __list_splice(const struct list_head *list,
				 struct list_head *prev,
				 struct list_head *next)
{
	struct list_head *first = list->next;
	struct list_head *last = list->prev;

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

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

static inline void list_splice(const struct list_head *list,
				struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head, head->next);
}

static inline void list_splice_tail(struct list_head *list,
				struct list_head *head)
{
	if (!list_empty(list))
		__list_splice(list, head->prev, head);
}

static inline void list_splice_init(struct list_head *list,
				    struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head, head->next);
		INIT_LIST_HEAD(list);
	}
}

static inline void list_splice_tail_init(struct list_head *list,
					 struct list_head *head)
{
	if (!list_empty(list)) {
		__list_splice(list, head->prev, head);
		INIT_LIST_HEAD(list);
	}
}

#define list_entry(ptr, type, member) \
	container_of(ptr, type, member)

#define list_first_entry(ptr, type, member) \
	list_entry((ptr)->next, type, member)

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

#define __list_for_each(pos, head) \
	for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_prev(pos, head) \
	for (pos = (head)->prev; pos != (head); pos = pos->prev)

#define list_for_each_safe(pos, n, head) \
	for (pos = (head)->next, n = pos->next; pos != (head); \
		pos = n, n = pos->next)

#define list_for_each_prev_safe(pos, n, head) \
	for (pos = (head)->prev, n = pos->prev; \
	     pos != (head); \
	     pos = n, n = pos->prev)

#define list_for_each_entry(pos, head, member)				\
	for (pos = list_entry((head)->next, typeof(*pos), member);	\
	     &pos->member != (head); 	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))


#define list_for_each_entry_reverse(pos, head, member)			\
	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
	     &pos->member != (head); 	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))

#define list_prepare_entry(pos, head, member) \
	((pos) ? : list_entry(head, typeof(*pos), member))

#define list_for_each_entry_continue(pos, head, member) 		\
	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head);	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each_entry_continue_reverse(pos, head, member)		\
	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
	     &pos->member != (head);	\
	     pos = list_entry(pos->member.prev, typeof(*pos), member))

#define list_for_each_entry_from(pos, head, member) 			\
	for (; &pos->member != (head);	\
	     pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each_entry_safe(pos, n, head, member)			\
	for (pos = list_entry((head)->next, typeof(*pos), member),	\
		n = list_entry(pos->member.next, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
		n = list_entry(pos->member.next, typeof(*pos), member);		\
	     &pos->member != (head);						\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

#define list_for_each_entry_safe_from(pos, n, head, member) 			\
	for (n = list_entry(pos->member.next, typeof(*pos), member);		\
	     &pos->member != (head);						\
	     pos = n, n = list_entry(n->member.next, typeof(*n), member))

#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
		n = list_entry(pos->member.prev, typeof(*pos), member);	\
	     &pos->member != (head); 					\
	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))

#define list_safe_reset_next(pos, n, member)				\
	n = list_entry(pos->member.next, typeof(*pos), member)

#endif

然后就是一个Makefile文件:

扫描二维码关注公众号,回复: 2463481 查看本文章
CC = gcc
CFLAGS = -Wall -g -O0

SRC1 = myapp.c kernellist.c
OBJ1 = myapp


$(OBJ1) : $(SRC1)
	   $(CC) $(CFLAGS) -o $@ $^
clean:
	$(RM) $(OBJ1)  .*.sw?

下面是执行后的效果:

猜你喜欢

转载自blog.csdn.net/qq_23922117/article/details/81143979
今日推荐