【发布时间】:2015-10-02 16:37:03
【问题描述】:
我想清除内核定义的类型列表。我有两个主要结构,num_wrapper 和 num。 num_wapper 有一个 num 列表,当我执行 del_all_node() 函数时内核崩溃。
我尝试标记list_del,内核不会崩溃。我不明白为什么会出现崩溃问题,因为我使用了 spin_lock 来保护这个 num_list。
任何提示将不胜感激。
以下是简化代码。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>
struct num_wrapper {
struct list_head num_list;
spinlock_t list_lock;
u8 check_num;
};
struct num {
struct list_head node;
int number;
struct num_wrapper* num_w_ptr;
};
s32 del_all_node(struct num_wrapper *number_wrap)
{
struct num *tmp;
struct num *num_head;
spin_lock(&number_wrap->list_lock);
list_for_each_entry_safe(num_head, tmp, &number_wrap->num_list, node) {
printk("num_head is %d\n", num_head->number);
list_del(&num_head->node);//this line seems to have problem
}
spin_unlock(&number_wrap->list_lock);
return 0;
}
static int __init hello_init(void)
{
/*Setup Scenario*/
struct num_wrapper *number_wrap = kzalloc(sizeof(struct num_wrapper)
, GFP_KERNEL);
struct num *number = kzalloc(sizeof(struct num), GFP_KERNEL);
number->number = 10;
number_wrap->check_num = 20;
INIT_LIST_HEAD(&number->node);
INIT_LIST_HEAD(&number_wrap->num_list);
list_add_tail(&number->node, &number_wrap->num_list);
del_all_node(number_wrap);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Good, haha\n");
}
module_init(hello_init);
module_exit(hello_exit);
更新
在做了一些调试之后,我似乎找到了根本原因...... 我的情况如下:
我有一个私有数据结构,它包含在 net_device 结构中。 以下是简化的场景:
struct xx_if *xx_if; //this is private data in net_device
struct xx_if *tmp;
list_for_each_entry_safe(xx_if, tmp, xx_if_wrap->if_list, list) {
free_netdev(xx_if->ndev);
list_del(&xx_if->list);
}
由于 free_netdev 也会释放私有数据 xx_if,所以代码被破坏了... 我的解决方法是将这两个语句的顺序更改为,它解决了崩溃问题。
奇怪的是我已经检查了 xx_if 是否为 NULL,但是如果我不交换这两个语句仍然会导致崩溃。
【问题讨论】:
-
是否有任何输出支持您的断言?你也可以展示一下吗?
-
你没有初始化
list_locknumber_wrap对象的成员:spin_lock_init(&number_wrap->list_lock); -
在我的真实代码中,我已经初始化了自旋锁
-
我在每条语句之后打印一些信息。发现list_del后的打印信息没有显示。顺便说一句,我启用了 CONFIG_LOCK_STAT,我发现 debug_locks_off 在 list_del 之后调用了很多次。
-
你没有在问题行中检查 NUL 指针的 num_head 指针
标签: c linux concurrency linux-kernel locking