您的位置:首页 > 编程语言

代码片段----内核链表使用一例

2014-03-06 10:08 169 查看
Makefile

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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: