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


    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
    ", a5->gp);
                printf("a5->on = %d
    ", a5->on);
                printf("a5->delay = %d
    ", a5->delay);
                printf("a5->count = %d
    ", a5->count);
    
                if (!list_empty(&gpio_list))
                {
                    list_del(q);
                    printf("free node %d
    ", a5->gp);
                    free(a5);
                }
            }
        }
    
        list_for_each_safe(q, q1, &gpio_list)
        {
            a5 = list_entry(q, GPIO_NODE, p);
    
            printf("a5->gp = %d
    ", a5->gp);
            printf("a5->on = %d
    ", a5->on);
            printf("a5->delay = %d
    ", a5->delay);
            printf("a5->count = %d
    ", a5->count);
    
            if (!list_empty(&gpio_list))
            {
                list_del(q);
                printf("free node %d
    ", 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,代表头节点

    使:

    1head.next= p1 ; head.prev = pn

    2p1.prev = headp1.next = p2;

    3p2.prev= p1 , p2.next = p3;

    npn.prev= pn-1 , pn.next = head

    以上,则构成了一个循环链表。

    p是嵌入到a中的,pa的地址偏移量可知,又因为head的地址可知,所以每个结构类型为A的链表节点a1...an的地址也是可以计算出的,从而可实现链表的遍历,在此基础上,则可以实现链表的各种操作。

    下面是从linux内核中移植出来的简单链表,list.h和list.c:

    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:

    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:

    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. }  
    27.   
    28. //删除节点,释放节点空间  
    29. int student_del(struct listnode *list,int id)  
    30. {  
    31.     struct listnode *node;  
    32.     student *stu;  
    33.     list_for_each(node,list){  
    34.         stu = node_to_item(node,student,_list);  
    35.         if(id == stu->id){  
    36.             printf("list_del, id:%d,name:%s ",stu->id,stu->name);  
    37.             list_remove(node);  
    38. #ifdef STUDENT_FREE_MEMORY    
    39.             //释放节点空间  
    40.             free(stu);  
    41.             stu = NULL;  
    42. #endif  
    43.             return 1;  
    44.               
    45.         }  
    46.           
    47.     }  
    48.   
    49.     return 0;  
    50. }  
    51.   
    52. //节点遍历  
    53. void student_foreach(struct listnode *list,student_foreach_fun fun,void *data)  
    54. {  
    55.     struct listnode *node;  
    56.     student *stu;  
    57.     list_for_each(node,list){  
    58.         stu = node_to_item(node,student,_list);  
    59.         fun(stu,data);  
    60.     }  
    61.   
    62. }  
    63.   
    64. //打印节点信息  
    65. void student_print(student *stu,void *data)  
    66. {  
    67.     printf("id:%d,name:%s ",stu->id,stu->name);  
    68. }  
    69.   
    70. int main()  
    71. {  
    72.     int i,len;  
    73.     student *stu;  
    74.     char *stu_name[]={"tonny","andy","michael","leslie","john"};  
    75.       
    76.       
    77.     len = sizeof(stu_name)/sizeof(stu_name[0]);  
    78.     //添加节点  
    79.     for(i=0;i<len;i++){  
    80.         stu = calloc(1,sizeof(student));  
    81.         stu->id = i + 1;  
    82.         stu->name = stu_name[i];  
    83.   
    84.         student_add(&student_list,stu);  
    85.     }  
    86.   
    87.     //打印所有节点  
    88.     student_foreach(&student_list,student_print,(void *)0);  
    89.       
    90.     //删除节点  
    91.     student_del(&student_list,1);  
    92.     student_foreach(&student_list,student_print,(void *)0);  
    93.   
    94.     //删除节点  
    95.     student_del(&student_list,5);  
    96.     student_foreach(&student_list,student_print,(void *)0);  
    97.       
    98.     return 0;  
    99.       
    100.   
    101. }  


    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)   
  • 相关阅读:
    PHP输出日志,json美化
    php获取项目路径
    16进制颜色,正则
    doctrine/instantiator
    cn.archive.ubuntu.com 慢的问题
    yzalis/identicon 像素头像
    Shell 判断进程是否存在
    shell 2>&1
    shell 判断是否继续
    shell
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/3583896.html
Copyright © 2020-2023  润新知