zoukankan      html  css  js  c++  java
  • 数据结构-内核的双向循环链表-简单实现

    list.h

    #ifndef LIST_H__
    #define LIST_H__
    
    struct list_head
    {
        struct list_head *prev ;
        struct list_head *next ;
    };
    
    #define LIST_HEAD_INIT(name)        { &(name), &(name) }
    #define LIST_HEAD(name)             struct list_head name = LIST_HEAD_INIT(name)
    #define __list_for_each(pos, head)  for (pos = (head)->next; pos != (head); pos = pos->next)
    
    
    /*
      const typeof( ((type *)0)->member ) *__mptr = (ptr);
         --->定义类型为(typeof获取member的类型)的指针* __mptr,并将ptr的值(实际地址)赋值给__mptr;
      (type *)( (char *)__mptr - offsetof(type,member) );
         --->用member实际的地址 - 偏移地址 就是数据结构实例的地址;
    */
    #define container_of(ptr, type, member) ({          
                const typeof( ((type *)0)->member ) *__mptr = (ptr);    
                (type *)( (char *)__mptr - offsetof(type,member) );})
    
    
    //offsetof宏:member成员到type结构实例类型的高度:
    //假设type结构的实例的地址是0 强转成char(*),再找到->member,就找到member距离结构体实例的偏移
    #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
    
    
    //ptr->cur:指向成员member的地址
    //member:成员在结构实例内部的名称,如果为数组,需要下标
    //type->struct score_st需要返回的结构实例类型
    #define list_entry(ptr, type, member)  container_of(ptr, type, member)
    
    
    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;
    }
    
    static inline void list_add(struct list_head *new, struct list_head *head)
    {
        __list_add(new, head, head->next);
    }
    
    
    #endif
    View Code

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "list.h"
    
    #define NAMESIZE    32
    //定义结构体
    struct score_st
    {
        int id ;
        char name[NAMESIZE] ;
        int math ;
        int chinese ;
        struct list_head node ;//*PREV *NEXT
    };
    //打印函数
    static void print_s(struct score_st *d) 
    {
        printf("%d %s %d %d 
    ",d->id ,d->name , d->math , d->chinese);
    }
    
    
    
    int main()
    {
        int i ; 
        struct score_st *datap ;
        struct list_head *cur ;
        //1.创建头
        LIST_HEAD(head);
        //2.头部插入8个节点并赋值
        for(i = 0 ; i < 8 ; i++)
        {   
            datap = malloc(sizeof(*datap));
            if(datap == NULL)
                exit(1);
            datap->id = i ; 
            snprintf(datap->name,NAMESIZE ,"stu%d",i);
            datap->math = rand()%100;
            datap->chinese = rand()%100;
            list_add(&datap->node,&head);
        }   
        //3.打印链表
        __list_for_each(cur, &head)
        {   
            datap = list_entry(cur,struct score_st,node);
            print_s(datap);
        }   
        //4.查找链表内部id为5的节点
        __list_for_each(cur, &head)
        {   
            datap = list_entry(cur,struct score_st,node);
            if(datap->id == 5)
                break;
        }   
        //5.查找结果并打印
        if(cur == &head)
            printf("can not find 
    ");
        else
            print_s(datap);
        exit(0);
    }
    View Code

    $:make main

    ps:内核的代码可以查看:

    root # cd /usr/src/kernels/2.6.32-358.el6.x86_64/include/linux/

    查找关键字:

    root # grep "#define container_of(" -R .
    //.  --->当前路径
    //R--->递归查找

    涉及到的.h文件有:

      kernel.h-----container_of

      list.h---------双向循环链表的实现

      stddef.h-----offsetof

  • 相关阅读:
    SDN课程阅读作业(2)
    2019 SDN上机第5次作业
    第01组 Alpha事后诸葛亮
    Windows 7 64位安装cURL
    html 空白汉字占位符&#12288;
    申请一个免费美国手机号码
    搭建网站需要学习什么(转自知乎)
    Eclipse 项目有红感叹号
    CSS字体大小之em,px,百分比
    题目1013:开门人和关门人
  • 原文地址:https://www.cnblogs.com/muzihuan/p/5239397.html
Copyright © 2011-2022 走看看