我试图让一个链表为我的模块工作,我没有使用内置内核链接列表(我不知道在我开始制作我的模块的时候)。
这是我的结构

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

我把头部作为全局变量。
struct data *head = NULL;

我有一个附加功能
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;
    }
}

在我的一个函数中,我使用这样的add_to_end
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);

但是当我试图使用这个链接列表中的msg时,会发生错误。内核将一些跟踪信息打印到终端。
我要做的是将消息复制到我的链接列表中,但作为单独的副本,而不仅仅是复制指向地址的指针。我读过一些例子,当复制两个结构时,它们实际上使用相同的地址,当更改其中一个时,它们都被更改了。我不要那种复印件,我要一份有自己地址的单独复印件。
我猜我复制这两个结构的方式不对,也许我的链表也不对,有人能帮我吗?

最佳答案

1)必须使用memecpy函数将消息内容复制到数据结构中。

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

2)如果消息是指向用户空间中的内存缓冲区的指针,则必须使用copy_from_user()函数而不是memcpy。此函数将处理用户空间到内核空间的内存复制。
3)请不要重新发明轮子。内核已经有了链接列表结构herel,您可以直接使用它而不是重新创建它。此外,如果列表可能由不同的线程访问,则在访问它之前必须用锁保护它们。
    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);

     }

07-24 09:47
查看更多