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

    内核链表

     内核链表是纯粹的链表结构,只有向前向后的两个指针。将内核链表嵌套到我们自己所写的,有数据的结构体里面,这样便可以将我们所输入的数据连接起来。
     参考文件:/usr/include/btrfs/list.h

    下面先来分析list.h的一些基本功能。

    插入数据

     内核链表有很多巧妙之处,比如这里无论是头插还是尾插都是调用函数__list_add来实现。

    static inline void __list_add(struct list_head *xnew,
                      struct list_head *prev,
                      struct list_head *next)
    {
        next->prev = xnew;
        xnew->next = next;
        xnew->prev = prev;
        prev->next = xnew;
    }
    

    头插数据

    static inline void list_add(struct list_head *xnew, struct list_head *head)
    {
        __list_add(xnew, head, head->next);
    }
    

    尾插数据

    static inline void list_add_tail(struct list_head *xnew, struct list_head *head)
    {
        __list_add(xnew, head->prev, head);
    }
    

    删除节点

     将链表中的某个节点删除。

    static inline void list_del_init(struct list_head *entry)
    {
    	__list_del(entry->prev, entry->next);
    	INIT_LIST_HEAD(entry);
    }
    
    static inline void __list_del(struct list_head * prev, struct list_head * next)
    {
    	next->prev = prev;
    	prev->next = next;
    }
    

    查找节点

     list_for_each将每个节点从链表中取出,list_entry将取出的节点进行运算,运算结果为用户定义的结构体地址(该节点)。通过遍历加list_entry运算,便可以访问链表中每一个数据的值,也可以将符合某个数据的值的节点地址返回。

    #define list_for_each(pos, head) 
    	for (pos = (head)->next; pos != (head); 
            	pos = pos->next)
    
    #define list_entry(ptr, type, member) 
    	((type*)((char * )(ptr) - (unsigned long)(&((type*)0)->member)))
    

    内核链表的使用

     创建一个.c文件,包含/usr/include/btrfs/list.h。通过以上功能的分析,已经可以实现链表的增,删,改,查的功能。

    #include "list.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdbool.h>
    #include <errno.h>
    
    typedef struct kernel_list{
    
        int data;
        struct list_head kernel_head;
    }my_kernel_list, *p_kernel_list;
    
    int input_msg(char * msg)
    {
        // 让用户输入新的数据
        int num ;
        printf("%s:" , msg);
        scanf("%d" , &num);
        while(getchar() != '
    ');
    
        return num;
    }
    
    p_kernel_list new_node()
    {
        p_kernel_list new = calloc(1, sizeof(my_kernel_list));
     
        if(NULL == new)
        {
            printf("Node creation failed
    ");
            return NULL;
        }
        INIT_LIST_HEAD(&new->kernel_head);
    
        return new;
    }
    
    void insert_node(p_kernel_list head)
    {
        p_kernel_list new = new_node();
    
        new->data = input_msg("Please enter the data for the header node");
    
        list_add(&new->kernel_head, &head->kernel_head);
    }
    
    bool display_list(p_kernel_list head)
    {
        if (list_empty(&head->kernel_head))
        {
            printf("The linked list is empty. Printing failed
    ");
            return false;
        }
    
        struct list_head *pos;
        p_kernel_list tmp;
        list_for_each(pos, &head->kernel_head)
        {
            tmp = list_entry(pos, my_kernel_list, kernel_head);
            printf("data:%d
    ", tmp->data);
        }
    }
    
    void add_tail_node(p_kernel_list head)
    {
        p_kernel_list new = new_node();
        new->data = input_msg("Please enter the data for the tail node");
    
        list_add_tail(&new->kernel_head, &head->kernel_head);
    }
    
    
    p_kernel_list find_node(p_kernel_list head, int fdata)
    {
        struct list_head *pos;
        p_kernel_list tmp;
    
        list_for_each(pos, &head->kernel_head)
        {
            tmp = list_entry(pos, my_kernel_list, kernel_head);
            if (tmp->data == fdata)
            {
                return tmp;
            }
        }
        return NULL;
    }
    
    bool del_node(p_kernel_list head)
    {   
        int del_data = input_msg("Please enter the data you want to delete");
        p_kernel_list del_pos;
    
        del_pos = find_node(head, del_data); 
        if (NULL == del_pos)
        {
            printf("Failed to delete. No data available
    ");
            return false;
        }   
        list_del_init(&del_pos->kernel_head);
    }
    
    bool replace_node(p_kernel_list head)
    {
     
        p_kernel_list new = new_node();
        p_kernel_list old_node;
        int del_data = input_msg("Please enter the data that needs to be replaced");
        old_node = find_node(head, del_data);
        if (NULL == old_node)
        {
            printf("Replacement failed. No data available
    ");   
            return false;
        }
    
        int new_data = input_msg("Please enter new data");
        new->data = new_data;
        list_replace_init(&old_node->kernel_head, &new->kernel_head);
      
    }
    
    int main(int argc, char const *argv[])
    {
        p_kernel_list head = new_node();
    
        insert_node(head);
        insert_node(head);
    
        add_tail_node(head);
        add_tail_node(head);
        display_list(head);
    
        del_node(head);   
        display_list(head);
    
        replace_node(head);
        display_list(head);
    
        return 0;
    }
    
  • 相关阅读:
    C语言 · 报时助手
    C语言 · 完美的代价
    C语言 · 十六进制转八进制
    C语言 · 十六进制转十进制
    C语言 · 芯片测试
    C语言 · 素数求和
    C语言 · 五次方数
    Lodop多分出空白页的可能(情况1)
    C-Lodop提示“网页还没下载完毕,请稍等一下再操作.”
    Lodop简答问答大全
  • 原文地址:https://www.cnblogs.com/ding-ding-light/p/14125352.html
Copyright © 2011-2022 走看看