Как я могу назначить заголовок связанного списка указателю в Linux ядре? - PullRequest
0 голосов
/ 31 января 2020

Я пишу программу для ядра Linux для реализации связанного списка и добавления даты рождения некоторых людей. После их добавления мне нужно найти максимальный возраст и удалить этот узел.

Чтобы найти узел с максимальным возрастом, я намереваюсь установить указатель на первый элемент связанного списка и сравнить возрасты, пока я выполняю его. Я не могу понять, как установить максимальный указатель на заголовок связанного списка.

Я пробовал несколько разных вещей, в том числе:

  • struct birthday * max = &birthday_list
  • struct birthday max = birthday_list
  • max = birthday_list.next;

Ошибка, которую я получаю: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]

Я думаю, что я мог бы назначить список другой структуре. Могу ли я получить некоторые разъяснения о том, что я могу делать неправильно?

#include<linux/list.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/types.h>
#include<linux/slab.h>

struct birthday {
    int day;
    int month;
    int year;
    struct list_head list;
}

static LIST_HEAD(birthday_list);
static void remove_oldest_student(void){
struct birthday *max, *curr, *next;
//point max to list head
max = LIST_HEAD(birthday_list);

list_for_each_entry(curr, &birthday_list, list){

  //find_max(&max, &curr);
}

    printk(KERN_INFO "Oldest Student Details --> Name: %s, Month: %d, Day: %d, Year: %d\n",max->name, max->month,max->day,max->year);
}


int simple_init(void) {
    struct birthday *ptr;
    int i;
    for(i = 0; i < 5; i++) {
        // create 5 birthday structs and add them to the list

        struct birthday *person;
        person = kmalloc(sizeof(*person), GFP_KERNEL);
        person->day = 22;
        person->month = 11;
        person->year = 1981;
        INIT_LIST_HEAD(&person->list);

        list_add_tail(&person->list, &birthday_list);
    }

    list_for_each_entry(ptr, &birthday_list, list) {
        // print the info from the structs to the log
        printk(KERN_INFO "%d, %d %d", ptr->month, ptr->day, ptr->year);
     }
remove_oldest_student();
    return 0;
    }


void simple_exit(void) {
    struct birthday *ptr, *next;
    list_for_each_entry_safe(ptr, next, &birthday_list, list) {
        // delete structs and return memory
        list_del(&ptr->list);
        kfree(ptr);
    }
}

module_init(simple_init);
module_exit(simple_exit);

Ответы [ 2 ]

1 голос
/ 31 января 2020

Я намереваюсь установить указатель на первый элемент связанного списка

Просто используйте list_first_entry macro:

max = list_first_entry(&birthday_list, struct birthday, list);

Подсказка: как вы уже указатель на первый элемент, нет необходимости повторять его в следующем l oop. Вместо list_for_each_entry вы можете использовать list_for_each_entry_continue:

// Make iterator to point to the already located element (first element in the list)
curr = max;
// Continue iteration.
// So the first iterated element will be the second element in the list
list_for_each_entry_continue(curr, &birthday_list, list){

  //find_max(&max, &curr);
}
1 голос
/ 31 января 2020

Я вижу несколько проблем, и я уверен, что это не единственная ошибка компиляции (например, max->name - такого элемента нет в структуре данных). Я также не хочу погружаться в логические ошибки, потому что это не имеет ничего общего с исходной проблемой, это типичная домашняя работа.
Давайте перейдем к делу.
Кажется, что вы пытаетесь получить указатель на struct из другого объекта struct, который содержится в нем (его член). Это может быть что-то вроде:

max = container_of(birthday_list.next, struct birthday, list);

Подробнее:
О container_of: SO post , guide , Linux kernel источник .
О list_head с красивой картинкой.


UPD: Как упоминал Циварев в своем ответе, есть функция list -API list_first_entry(), что в конечном итоге вызывает container_of(). Так что, если вам все еще действительно нужно этой первой записи - лучше использовать функцию API. container_of() просто для лучшего понимания происходящего.

...