代码片段----内核链表使用一例
2014-03-06 10:08
169 查看
Makefile
main.c
list.h
http://files.cnblogs.com/pengdonglin137/list.rar
参考:http://blog.csdn.net/xnwyd/article/details/7359373
Linux内核链表的核心思想是:在用户自定义的结构A中声明list_head类型的成员p,这样每个结构类型为A的变量a中,都拥有同样的成员p,如下:
struct A{
int property;
struct list_head p;
}
其中,list_head结构类型定义如下:
struct list_head {
struct list_head *next,*prev;
};
list_head拥有两个指针成员,其类型都为list_head,分别为前驱指针prev和后驱指针next。
假设:
(1)多个结构类型为A的变量a1...an,其list_head结构类型的成员为p1...pn
(2)一个list_head结构类型的变量head,代表头节点
使:
(1)head.next= p1 ; head.prev = pn
(2)p1.prev = head,p1.next = p2;
(3)p2.prev= p1 , p2.next = p3;
…
(n)pn.prev= pn-1 , pn.next = head
以上,则构成了一个循环链表。
因p是嵌入到a中的,p与a的地址偏移量可知,又因为head的地址可知,所以每个结构类型为A的链表节点a1...an的地址也是可以计算出的,从而可实现链表的遍历,在此基础上,则可以实现链表的各种操作。
下面是从linux内核中移植出来的简单链表,list.h和list.c:
list.h:
[cpp] view plaincopy
#ifndef _INIT_LIST_H_
#define _INIT_LIST_H_
#ifndef offsetof
/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
struct listnode
{
struct listnode *next;
struct listnode *prev;
};
#define node_to_item(node, container, member) \
(container *) (((char*) (node)) - offsetof(container, member))
#define list_declare(name) \
struct listnode name = { \
.next = &name, \
.prev = &name, \
}
#define list_for_each(node, list) \
for (node = (list)->next; node != (list); node = node->next)
#define list_for_each_reverse(node, list) \
for (node = (list)->prev; node != (list); node = node->prev)
void list_init(struct listnode *list);
void list_add_tail(struct listnode *list, struct listnode *item);
void list_remove(struct listnode *item);
#define list_empty(list) ((list) == (list)->next)
#define list_head(list) ((list)->next)
#define list_tail(list) ((list)->prev)
#endif
list.c:
[cpp] view plaincopy
#include "list.h"
void list_init(struct listnode *node)
{
node->next = node;
node->prev = node;
}
void list_add_tail(struct listnode *head, struct listnode *item)
{
item->next = head;
item->prev = head->prev;
head->prev->next = item;
head->prev = item;
}
void list_remove(struct listnode *item)
{
item->next->prev = item->prev;
item->prev->next = item->next;
}
测试代码list_test.c:
[cpp] view plaincopy
#include<stdio.h>
#include<stdlib.h>
#include "list.h"
#define STUDENT_FREE_MEMORY
//声明链表节点
typedef struct {
int id;
char *name;
struct listnode _list;
}student;
//遍历函数指针
typedef void (*student_foreach_fun)(student *stu,void *data);
//声明链表
static list_declare(student_list);
//添加节点
int student_add(struct listnode *list,student *stu)
{
list_init(&stu->_list);
list_add_tail(list,&stu->_list);
}
//删除节点,释放节点空间
int student_del(struct listnode *list,int id)
{
struct listnode *node;
student *stu;
list_for_each(node,list){
stu = node_to_item(node,student,_list);
if(id == stu->id){
printf("list_del, id:%d,name:%s\n",stu->id,stu->name);
list_remove(node);
#ifdef STUDENT_FREE_MEMORY
//释放节点空间
free(stu);
stu = NULL;
#endif
return 1;
}
}
return 0;
}
//节点遍历
void student_foreach(struct listnode *list,student_foreach_fun fun,void *data)
{
struct listnode *node;
student *stu;
list_for_each(node,list){
stu = node_to_item(node,student,_list);
fun(stu,data);
}
}
//打印节点信息
void student_print(student *stu,void *data)
{
printf("id:%d,name:%s\n",stu->id,stu->name);
}
int main()
{
int i,len;
student *stu;
char *stu_name[]={"tonny","andy","michael","leslie","john"};
len = sizeof(stu_name)/sizeof(stu_name[0]);
//添加节点
for(i=0;i<len;i++){
stu = calloc(1,sizeof(student));
stu->id = i + 1;
stu->name = stu_name[i];
student_add(&student_list,stu);
}
//打印所有节点
student_foreach(&student_list,student_print,(void *)0);
//删除节点
student_del(&student_list,1);
student_foreach(&student_list,student_print,(void *)0);
//删除节点
student_del(&student_list,5);
student_foreach(&student_list,student_print,(void *)0);
return 0;
}
Makefile:
[cpp] view plaincopy
TARGET=list_test
SRC=list_test.c list.c
#SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
CFLAGS=-g -Wall -o
$(TARGET):$(SRC)
gcc $(SRC) $(CFLAGS) $(TARGET)
clean:
rm $(OBJ) $(TARGET)
CC=gcc main:main.o clean: $(RM) *.o main .PHONY:clean
main.c
#include "list.h" #include <stdio.h> typedef struct { unsigned long gp; // (group<<3)|(pnum&0x7) unsigned long on; // on or off unsigned long delay; unsigned long count; struct list_head p; }GPIO_NODE; int main(int argc, const char *argv[]) { GPIO_NODE *a1; GPIO_NODE *a2; GPIO_NODE *a3; GPIO_NODE *a4; struct list_head *q = NULL; struct list_head *q1 = NULL; GPIO_NODE *a5; LIST_HEAD(gpio_list); a1 = (GPIO_NODE *)malloc(sizeof(GPIO_NODE)); a2 = (GPIO_NODE *)malloc(sizeof(GPIO_NODE)); a3 = (GPIO_NODE *)malloc(sizeof(GPIO_NODE)); a4 = (GPIO_NODE *)malloc(sizeof(GPIO_NODE)); a1->gp = 1; a1->on = 1; a1->delay = 1; a1->count = 1; a2->gp = 2; a2->on = 2; a2->delay = 2; a2->count = 2; a3->gp = 3; a3->on = 3; a3->delay = 3; a3->count = 3; a4->gp = 4; a4->on = 4; a4->delay = 4; a4->count = 4; list_add_tail(&(a1->p), &gpio_list); list_add_tail(&(a2->p), &gpio_list); list_add_tail(&(a3->p), &gpio_list); list_add_tail(&(a4->p), &gpio_list); list_for_each_safe(q, q1, &gpio_list) { a5 = list_entry(q, GPIO_NODE, p); if(a5->gp > 3) { printf("a5->gp = %d\n", a5->gp); printf("a5->on = %d\n", a5->on); printf("a5->delay = %d\n", a5->delay); printf("a5->count = %d\n", a5->count); if (!list_empty(&gpio_list)) { list_del(q); printf("free node %d\n", a5->gp); free(a5); } } } list_for_each_safe(q, q1, &gpio_list) { a5 = list_entry(q, GPIO_NODE, p); printf("a5->gp = %d\n", a5->gp); printf("a5->on = %d\n", a5->on); printf("a5->delay = %d\n", a5->delay); printf("a5->count = %d\n", a5->count); if (!list_empty(&gpio_list)) { list_del(q); printf("free node %d\n", a5->gp); free(a5); } } return 0; }
list.h
http://files.cnblogs.com/pengdonglin137/list.rar
参考:http://blog.csdn.net/xnwyd/article/details/7359373
Linux内核链表的核心思想是:在用户自定义的结构A中声明list_head类型的成员p,这样每个结构类型为A的变量a中,都拥有同样的成员p,如下:
struct A{
int property;
struct list_head p;
}
其中,list_head结构类型定义如下:
struct list_head {
struct list_head *next,*prev;
};
list_head拥有两个指针成员,其类型都为list_head,分别为前驱指针prev和后驱指针next。
假设:
(1)多个结构类型为A的变量a1...an,其list_head结构类型的成员为p1...pn
(2)一个list_head结构类型的变量head,代表头节点
使:
(1)head.next= p1 ; head.prev = pn
(2)p1.prev = head,p1.next = p2;
(3)p2.prev= p1 , p2.next = p3;
…
(n)pn.prev= pn-1 , pn.next = head
以上,则构成了一个循环链表。
因p是嵌入到a中的,p与a的地址偏移量可知,又因为head的地址可知,所以每个结构类型为A的链表节点a1...an的地址也是可以计算出的,从而可实现链表的遍历,在此基础上,则可以实现链表的各种操作。
下面是从linux内核中移植出来的简单链表,list.h和list.c:
list.h:
[cpp] view plaincopy
#ifndef _INIT_LIST_H_
#define _INIT_LIST_H_
#ifndef offsetof
/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
struct listnode
{
struct listnode *next;
struct listnode *prev;
};
#define node_to_item(node, container, member) \
(container *) (((char*) (node)) - offsetof(container, member))
#define list_declare(name) \
struct listnode name = { \
.next = &name, \
.prev = &name, \
}
#define list_for_each(node, list) \
for (node = (list)->next; node != (list); node = node->next)
#define list_for_each_reverse(node, list) \
for (node = (list)->prev; node != (list); node = node->prev)
void list_init(struct listnode *list);
void list_add_tail(struct listnode *list, struct listnode *item);
void list_remove(struct listnode *item);
#define list_empty(list) ((list) == (list)->next)
#define list_head(list) ((list)->next)
#define list_tail(list) ((list)->prev)
#endif
list.c:
[cpp] view plaincopy
#include "list.h"
void list_init(struct listnode *node)
{
node->next = node;
node->prev = node;
}
void list_add_tail(struct listnode *head, struct listnode *item)
{
item->next = head;
item->prev = head->prev;
head->prev->next = item;
head->prev = item;
}
void list_remove(struct listnode *item)
{
item->next->prev = item->prev;
item->prev->next = item->next;
}
测试代码list_test.c:
[cpp] view plaincopy
#include<stdio.h>
#include<stdlib.h>
#include "list.h"
#define STUDENT_FREE_MEMORY
//声明链表节点
typedef struct {
int id;
char *name;
struct listnode _list;
}student;
//遍历函数指针
typedef void (*student_foreach_fun)(student *stu,void *data);
//声明链表
static list_declare(student_list);
//添加节点
int student_add(struct listnode *list,student *stu)
{
list_init(&stu->_list);
list_add_tail(list,&stu->_list);
}
//删除节点,释放节点空间
int student_del(struct listnode *list,int id)
{
struct listnode *node;
student *stu;
list_for_each(node,list){
stu = node_to_item(node,student,_list);
if(id == stu->id){
printf("list_del, id:%d,name:%s\n",stu->id,stu->name);
list_remove(node);
#ifdef STUDENT_FREE_MEMORY
//释放节点空间
free(stu);
stu = NULL;
#endif
return 1;
}
}
return 0;
}
//节点遍历
void student_foreach(struct listnode *list,student_foreach_fun fun,void *data)
{
struct listnode *node;
student *stu;
list_for_each(node,list){
stu = node_to_item(node,student,_list);
fun(stu,data);
}
}
//打印节点信息
void student_print(student *stu,void *data)
{
printf("id:%d,name:%s\n",stu->id,stu->name);
}
int main()
{
int i,len;
student *stu;
char *stu_name[]={"tonny","andy","michael","leslie","john"};
len = sizeof(stu_name)/sizeof(stu_name[0]);
//添加节点
for(i=0;i<len;i++){
stu = calloc(1,sizeof(student));
stu->id = i + 1;
stu->name = stu_name[i];
student_add(&student_list,stu);
}
//打印所有节点
student_foreach(&student_list,student_print,(void *)0);
//删除节点
student_del(&student_list,1);
student_foreach(&student_list,student_print,(void *)0);
//删除节点
student_del(&student_list,5);
student_foreach(&student_list,student_print,(void *)0);
return 0;
}
Makefile:
[cpp] view plaincopy
TARGET=list_test
SRC=list_test.c list.c
#SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
CFLAGS=-g -Wall -o
$(TARGET):$(SRC)
gcc $(SRC) $(CFLAGS) $(TARGET)
clean:
rm $(OBJ) $(TARGET)
相关文章推荐
- 内核链表实现分析与使用(双向环形链表)
- [精华]]Linux内核2.6.14源码分析-双向循环链表代码分析(转)
- 为AM335x移植Linux内核主线代码(35)使用platform中的GPIO
- 代码生成工具之事物使用片段
- 类成员函数指针的使用,代码片段供参考
- 使用emacs作为代码片段管理工具
- 用GO帮朋友写了一个批量群发的软件,其中一个需求是使用rsa登录ssh,代码片段分享.
- 内核代码中和用户栈相关的几个片段
- 如何使用gdb调试android webkit内核代码
- 使用JavaScript实现链表的数据结构的代码
- 如何使用gdb调试android webkit内核代码
- android开发过程中使用功能性代码片段(二)
- Linux 内核链表使用举例
- Linux2.6.32内核笔记(5)在应用程序中移植使用内核链表【转】
- Unity3d使用心得(1):ModelImporter的使用、在代码中添加动画片段。
- 使用github管理xcode代码片段的实践
- 03_MyBatis基本查询,mapper文件的定义,测试代码的编写,resultMap配置返回值,sql片段配置,select标签标签中的内容介绍,配置使用二级缓存,使用别名的数据类型,条件查询ma
- 使用linux 内核中代码之--list
- 在多个页面使用同一个HTML片段的代码
- 使用vim+cscope/ctags阅读内核代码