2015-10-02 30 views
0

我想清除一個由Kernel定義的類型列表。我有兩個主要的結構體,num_wrapper和num。 num_wapper有一個num列表,當我執行del_all_node()函數時內核崩潰。linux-kernel中自旋鎖併發的內核崩潰

我嘗試標記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,但如果我不交換這兩個語句,仍然會導致崩潰。

+0

是否有支持斷言的輸出?你能證明嗎? – HuStmpHrrr

+1

您沒有初始化'number_wrap'對象的'list_lock'成員:'spin_lock_init(&number_wrap-> list_lock);' – Tsyvarev

+0

在我的真實代碼中,我初始化了自旋鎖 –

回答

0

我並不清楚地瞭解下面的代碼:

INIT_LIST_HEAD(&number->node); 
INIT_LIST_HEAD(&number_wrap->num_list); 
list_add_tail(&number->node, &number_wrap->num_list); 

您初始化兩種不同的結構,然後添加一個類型列表中的另一種類型的列表。

難道你可以這樣做嗎?

我認爲,你需要的東西是這樣的:

struct num{ 
     u8 check_num; 
     struct list_head list; 
    }; 

    struct num_wrapper{ 
     struct num* num_ptr; 
     spinlock_t list_lock; 
    }; 

    int init_num_wrapper(struct num_wrapper** prt){ 
     if(!ptr && *ptr){ 
      return -EINVAL; 
     } 

     *ptr = kzalloc(sizeof(struct num_wrapper), GFP_KERNEL); 
     if(!*ptr){ 
      return -ENOMEM; 
     } 
     INIT_LIST_HEAD(& (*ptr)->num_ptr->list); 
     ... init spinlock 
     return 0; 
    } 

    int add_num(num_wrapper* prt_wrap, u8 check_num){ 
     ... checking pointers 
     struct num num* = NULL; 
     num = kmalloc(sizeof(struct num), GFP_KERNEL); 
     if(! num){ 
      return -ENOMEM; 
     } 

     INIT_LIST_HEAD(&num->list); 
     num->check_num = check_num; 
     spin_lock(&prt_wrap->list_lock); 
     list_add_tail(&num->list, &prt_wrap->num_ptr.list); 
     spin_unlock(&prt_wrap->list_lock); 
     return 0; 
    } 

    int remove_all_nodes(num_wrapper* prt_wrap){ 
     ... checking pointer 
     struct num *tmp = NULL;  
     struct num *num_head = NULL; 
     spin_lock(&number_wrap->list_lock); 
     list_for_each_entry_safe(num_head, tmp, &prt_wrap->list, list) 
     { 
      printk("num_head is %d\n", num_head->number); 
      list_del(&num_head->node);//this line seems to have problem 
     } 
     spin_unlock(&num_wrapper->list_lock); 
     return 0; 
    } 

更新

然後,您可以使用上述功能num_wrapper的操縱。 例如:

//... 
    struct num_wrapper* nums = NULL; 
    init_num_wrapper(&nums); // after this call, you will have inited nums var, which can be used with others functions for manipulating with num_wrapper list. 
    u8 num = 2; 
    add_num(nums, num); // after this call new node with num will be added to num_wrapper 
    //... 
+0

其實我想要的是,num_wrapper可以存儲num_list的頭部,並且只有一個num_wrapper,但是一個num結構的列表 –

+0

我不確定我是否理解你的init_wrapper函數。你能舉一個例子如何使用你的功能? –