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