简体   繁体   中英

making a linked list in kernel module

I was trying to make a linked list working for my module, I am not using the build-in kernel linked list( I don't know that thing exist at the moment when I started making my module). here is my struct

struct data{
    struct data *next;
    struct msghdr *msg;
    size_t len;
}

I make a head as global variable.

struct data *head = NULL;

I have a add_to_end function

void add_to_end(struct data *newData){
    struct data *temp1;
    if (head == NULL){
        head = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
        head = newData;
    } else {
        temp1 = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
        temp1 = head;
        while(temp1->next!=NULL) {
            temp1 = temp->next;
        }
        temp1->next = newData;
    }
}

in one of my functions, I use add_to_end like this

struct data *temp;

temp = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
temp->next = NULL;
temp->msg = (struct msghdr *)kmalloc(sizeof(struct msghdr),GFP_KERNEL);
temp->msg = message;
temp->len = length;
add_to_end(temp);

but when I am trying to use the msg in this linked list, error happens. The kernel print some trace thing to the terminal. What I want to do is copy the message into my linked list, but as a separate copy, not just copying the pointer that point to the address. I have read some examples that when copying two struct, they actually using the same address, when changing one of them, both of them got changed. I don't want that kind of copy, I want a separate copy with its own address.

I am guessing that the way that I copy the two struct is not right and maybe my linked list is not right too, can someone help me please?

There are a number of places in your sample where you are allocating memory, then immediately leaking the pointer by overwriting it:

    head = (struct data *)kmalloc(sizeof(struct data),GFP_KERNEL);
    head = newData;

This doesn't make sense. Either your function should be passed in the contents of a linked list entry that it should be adding (eg, msg and len ), or it should treat the value of newData that is being passed in as already having been allocated.

I would strongly recommend that you brush up on your use of linked lists by working some examples in userspace before venturing into the kernel. If nothing else, recovering from errors and performing debugging will be much easier there.

1) You have to use memecpy function to copy content from message to your data structure.

    temp->msg = (struct msghdr *)kmalloc(sizeof(struct msghdr),GFP_KERNEL);
    // temp->msg = message;
    memcpy(temp->msg, message, sizeof(struct msghdr));

2) If the message is pointer point to a memory buffer in user space, you have to use the copy_from_user() function instead of memcpy. This function will handle the user space to kernel space memory copy.

3) Please do not reinvent the wheel. The kernel already has link list structure here l and your can just use it rather than recreate it. Besides, if the list may be access by different threads, you have to protect them by a lock before access it.

    DEFINE_RAW_SPINLOCK(mylock);
    LIST_HEAD(vm_list);

    ....
    my_function() {
            ....
        raw_spin_lock(&kvm_lock);
        list_for_each_entry(kvm, &vm_list, vm_list)
            *val += *(u32 *)((void *)kvm + offset);
        raw_spin_unlock(&kvm_lock);

     }

In while loop you have temp instead of temp1 in add_to_end function. Do you really run this code or this mistake is just in this post?

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