具有唯一列表ID的链表的C实现

时间:2019-12-27 19:04:37

标签: c data-structures linked-list implementation

我需要在内核代码中实现一个链表(不确定是否太重要)。该代码应使用0到255之间的数字来标识每个链接列表。每个节点在列表和一些其他数据字段中还具有一个ID。我在使其无法正常工作时遇到一些麻烦,并且不确定出了什么问题我已经非常清楚地编写了它,但是似乎存在细分问题。我很高兴了解这里出了什么问题。

注意:我很确定问题不在于它正在使用内核函数。

#undef __KERNEL__
#define __KERNEL__
#undef MODULE
#define MODULE
#include <linux/kernel.h>  
#include <linux/module.h>  
#include <linux/fs.h>       
#include <linux/uaccess.h>  
#include <linux/string.h>   

MODULE_LICENSE("GPL");

typedef struct Node { 
    long node_id;
    char data[256];
    int data_size;
    struct Node next;
};

typedef struct List { 
    int list_id;
    struct Node head;
};

/* array holds the Lists by their list_id number */
static struct List* lists = (List*) kmalloc(256 * sizeof(List), GFP_KERNEL);

static struct List* get_list(int list_id) {
    return lists[list_id];
}

static struct Node* get_node(struct List* list, long node_id) {
    struct Node* node = list->head;
    while (node != NULL) {
        if (node->node_id == node_id) {
            return node;
        }
        node = node->next;
    }
    return NULL;
}

static void add_node(struct List* list, long node_id) {
    struct Node* node;
    node = kmalloc(sizeof(Node), GFP_KERNEL);
    node->next = list->head;
    list->head = node;
}

static void add_list(int list_id) {
    struct List* list;
    list = kmalloc(sizeof(List), GFP_KERNEL);
    list->list_id = list_id;
    lists[list->list_id] = list;
}

static void free_list(struct List* list) {
    if (list == NULL) {
        return;
    }
    while (list->head != NULL) {
        struct Node* node = list->head;
        list->head = node->next;
        kfree(node);
    }
    kfree(list);
}

static void free_lists(void) {
    int list_id;
    for (list_id = 0 ; list_id < 256; list_id++) {
        free_list(lists[list_id]);
    }
}

1 个答案:

答案 0 :(得分:1)

struct Node next;

您的struct Node定义中的这一行特别创建了非终止递归,其中struct Node需要另一个定义的struct Node才能被正确定义,而后者又需要另一个struct Node,等等:

Defining this struct will never be completed as a new struct must be defined each time

我们使用指针是因为我们可以使用NULL终止链表,这意味着除其他外,不再有节点可以连接:

A null pointer can terminate the allocation of nodes.

我假设您正在尝试以这种方式实现链接列表和节点,就像它们是函数中的指针一样,其中最著名的是get_list

关于kmalloc的另一件事值得一提:

  

kmalloc是为内核中小于页面大小的对象分配内存的常规方法。

Although I've read that kmalloc can allocate way more memory than this default page size in modern kernels,我不知道您使用的是哪个Linux版本或环境。进行以下假设,您可能需要重新考虑这些数据结构的整体实现,或者至少重新考虑kmalloc的使用:

  1. Linux使用的默认页面大小为4kb
  2. 您的Node结构使用8个字节的指针,4个字节的整数,1个字节的字符和8个字节的长整数,占用276个字节。
  3. 您的List结构(添加另一个整数)占用280个字节。
  4. static struct List* lists分配的大小是List结构的256倍,舍入后最大为72kb,这比页面大小还要大。

对于一个,我建议您有一个使用头节点的指针的列表,而不是让列表存储头本身。我还建议您将char data[256]设为dynamic array,并且最大容量为256,这样也可以节省一些空间。我还建议您使用指向列表的指针数组(static struct List* lists[256],而不是static struct List* listsstatic struct List lists[256])。