zoukankan      html  css  js  c++  java
  • linux内核链表使用

    原文链接: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:

    #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.h
     1 #ifndef _INIT_LIST_H_
     2 #define _INIT_LIST_H_
     3 
     4 #ifndef offsetof
     5 /* Offset of member MEMBER in a struct of type TYPE. */
     6 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
     7 #endif
     8 
     9 struct listnode
    10 {
    11     struct listnode *next;
    12     struct listnode *prev;
    13 };
    14 
    15 #define node_to_item(node, container, member) 
    16     (container *) (((char*) (node)) - offsetof(container, member))
    17 
    18 #define list_declare(name) 
    19     struct listnode name = { 
    20         .next = &name, 
    21         .prev = &name, 
    22     }
    23 
    24 #define list_for_each(node, list) 
    25     for (node = (list)->next; node != (list); node = node->next)
    26 
    27 #define list_for_each_reverse(node, list) 
    28     for (node = (list)->prev; node != (list); node = node->prev)
    29 
    30 void list_init(struct listnode *list);
    31 void list_add_tail(struct listnode *list, struct listnode *item);
    32 void list_remove(struct listnode *item);
    33 
    34 #define list_empty(list) ((list) == (list)->next)
    35 #define list_head(list) ((list)->next)
    36 #define list_tail(list) ((list)->prev)
    37 
    38 #endif

    list.c:

    #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.c
     1 #include "list.h"
     2 
     3 void list_init(struct listnode *node)
     4 {
     5     node->next = node;
     6     node->prev = node;
     7 }
     8 
     9 void list_add_tail(struct listnode *head, struct listnode *item)
    10 {
    11     item->next = head;
    12     item->prev = head->prev;
    13     head->prev->next = item;
    14     head->prev = item;
    15 }
    16 
    17 void list_remove(struct listnode *item)
    18 {
    19     item->next->prev = item->prev;
    20     item->prev->next = item->next;
    21 }

    测试代码list_test.c:

    #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);
            return 0;
    }
    
    //删除节点,释放节点空间
    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
    ",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
    ",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;
        
    
    }
        
    list_test.c
      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include "list.h"
      4 
      5 #define STUDENT_FREE_MEMORY
      6 
      7 //声明链表节点
      8 typedef struct {
      9     int id;
     10     char *name;
     11     struct listnode _list;
     12 }student;
     13 
     14 //遍历函数指针
     15 typedef void (*student_foreach_fun)(student *stu,void *data);
     16 
     17 
     18 //声明链表
     19 static list_declare(student_list);
     20 
     21 //添加节点
     22 int student_add(struct listnode *list,student *stu)
     23 {
     24     list_init(&stu->_list);
     25     list_add_tail(list,&stu->_list);    
     26     return 0;
     27 }
     28 
     29 //删除节点,释放节点空间
     30 int student_del(struct listnode *list,int id)
     31 {
     32     struct listnode *node;
     33     student *stu;
     34     list_for_each(node,list){
     35         stu = node_to_item(node,student,_list);
     36         if(id == stu->id){
     37             printf("list_del, id:%d,name:%s
    ",stu->id,stu->name);
     38             list_remove(node);
     39 #ifdef STUDENT_FREE_MEMORY    
     40             //释放节点空间
     41             free(stu);
     42             stu = NULL;
     43 #endif
     44             return 1;
     45             
     46         }
     47         
     48     }
     49 
     50     return 0;
     51 }
     52 
     53 //节点遍历
     54 void student_foreach(struct listnode *list,student_foreach_fun fun,void *data)
     55 {
     56     struct listnode *node;
     57     student *stu;
     58     list_for_each(node,list){
     59         stu = node_to_item(node,student,_list);
     60         fun(stu,data);
     61     }
     62 
     63 }
     64 
     65 //打印节点信息
     66 void student_print(student *stu,void *data)
     67 {
     68     printf("id:%d,name:%s
    ",stu->id,stu->name);
     69 }
     70 
     71 int main()
     72 {
     73     int i,len;
     74     student *stu;
     75     char *stu_name[]={"tonny","andy","michael","leslie","john"};
     76     
     77     
     78     len = sizeof(stu_name)/sizeof(stu_name[0]);
     79     //添加节点
     80     for(i=0;i<len;i++){
     81         stu = calloc(1,sizeof(student));
     82         stu->id = i + 1;
     83         stu->name = stu_name[i];
     84 
     85         student_add(&student_list,stu);
     86     }
     87 
     88     //打印所有节点
     89     student_foreach(&student_list,student_print,(void *)0);
     90     
     91     //删除节点
     92     student_del(&student_list,1);
     93     student_foreach(&student_list,student_print,(void *)0);
     94 
     95     //删除节点
     96     student_del(&student_list,5);
     97     student_foreach(&student_list,student_print,(void *)0);
     98     
     99     return 0;
    100     
    101 
    102 }

     Makefile:

    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) 
    Makefile
     1 TARGET=list_test
     2 SRC=list_test.c list.c
     3 #SRC=$(wildcard *.c)
     4 OBJ=$(SRC:.c=.o)
     5 CFLAGS=-g -Wall -o
     6 
     7 $(TARGET):$(SRC)
     8     gcc $(SRC) $(CFLAGS) $(TARGET)
     9 clean:
    10     rm $(OBJ) $(TARGET) 
  • 相关阅读:
    IOS开发系列之阿堂教程:玩转IPhone客户端和Web服务端交互(客户端)实践
    详解基于linux环境MySQL搭建与卸载
    详解Redis基本命令
    浅谈基于Linux的Redis环境搭建
    浅谈Linux基本命令
    浅谈基于Intellij IDEA Maven的配置与使用
    浅谈SpringMVC执行过程
    浅析关于java的一些基础问题(上篇)
    软件架构应关心的若干要素
    详解mybatis映射配置文件
  • 原文地址:https://www.cnblogs.com/hubery/p/4556983.html
Copyright © 2011-2022 走看看