简体   繁体   中英

How can I assign the head of a linked list to a pointer in Linux kernel?

I am writing a program for the Linux kernel to implement a linked list and add the date of births of some people. After they are added I need to find the max age and delete that node.

To find the node with max age, I intend to set a pointer to the first element of the linked list and compare the ages as I iterate through it. I can't figure out how to set the max pointer to the head of the linked list.

I have tried a couple of different things including:

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

Error I get: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]

I think I might be assigning a list to a different structure. Can I get some clarification on what I might be doing wrong?

#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);

I see several problems and I'm sure it's not the only one compile error (eg max->name - there is no such member in data structure). I also don't want to dive into logical errors, because it has nothing to do with the original problem, it's typical homework.
Let's get to the point.
Seems that you're trying to obtain the pointer to struct from another struct object, which is contained in it (its member). It could be something like:

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

Read more:
About container_of : SO post , guide , Linux kernel source .
About list_head with nice picture.


UPD: As Tsyvarev mentioned in his answer, there is a list -API function list_first_entry() , which eventually invokes container_of() . So if you still really need that first entry - it's better to use an API function. container_of() is just for better understanding of what's going on.

I intend to set a pointer to the first element of the linked list

Just use list_first_entry macro:

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

Hint: as you already have a pointer to the first element, there is no need to iterate it in the following loop. Instead of list_for_each_entry you may use 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);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM