2009-12-13 41 views
0

我正在編寫一些linux內核代碼,並且遇到了一個奇怪的內核恐慌。使用struct導致內核恐慌?

我有一個鏈接列表,我維護內核的內置宏(include/linux/list.h)。如果列表爲空,則分配以下結構的實例:

struct time_span 
{ 
    struct timeval start; 
    struct timeval end; 
}; 

並使用名爲「tmp」的指針指向它。我將tmp添加到我使用list_add_tail()維護的列表中。如果列表不是空的(我試圖用一個列表項來測試以簡化調試),我使用tmp指向列表中的第一項並嘗試打印出tmp-> tmp的內容, end.tv_sec。不幸的是,這導致內核恐慌。

tmp不是NULL(我在運行時檢查),也不是「tmp-> end」(我可以同時打印)。只有當我嘗試訪問「結束」中的某個字段時,纔會發生內核恐慌。我從來沒有見過這樣的事情 - 有沒有人有任何想法?

感謝您的幫助!

------- ------編輯

代碼示例(這個住在一個將被反覆調用的函數):

// ......... 
struct timeval now_tv; 
do_gettimeofday(&now_tv); 
if(!list_empty(&(my_list.time_list))) 
    { 
     tmp = list_first_entry(&(my_list.time_list), struct time_span, time_list); 
     if(tmp != NULL) 
     { 
        tmp->end.tv_sec = now_tv.tv_sec; // THIS BREAKS 
                // Attempting to print "tmp->end.tv_sec" also breaks. 
      tmp->end.tv_usec = now_tv.tv_usec; 
     } 
    } 

     // ......... 

    if(list_empty(&(my_list.time_list))) 
     { 
     new_time_span = (struct time_span *) kmalloc(sizeof(struct time_span), GFP_KERNEL); 
     INIT_LIST_HEAD(&(new_time_span->time_list)); 
     list_add_tail(&(new_time_span->time_list), &(my_list.time_list)); 
      do_gettimeofday(&(new_time_span->start)); 
    } 

    // ........ 
+3

後一些代碼,說明了這個問題。 – 2009-12-13 16:21:25

+0

具體來說,訪問'tmp-> end'上的代碼(以及它周圍的代碼)。 – 2009-12-13 16:22:52

+1

您是否正在檢查輸入到列表中的結構地址,以及何時將它從列表中刪除? my_list.time_list是否正確初始化? – 2009-12-13 17:36:32

回答

4

你錯過了一些基本面關於Linux鏈接列表。 以下應改變:

struct time_span 
{ 
    struct timeval start; 
    struct timeval end; 
}; 

要:

struct time_span 
{ 
    struct timeval start; 
    struct timeval end; 
    struct list_head time_list; 
} 

當使用Linux鏈表,你應該把你的結構內部的結構LIST_HEAD想要的清單。
在下面的代碼中,您將分配一個類型struct time_span並在分配的變量new_time_span內引用一個名爲time_list的變量...但您尚未將其添加到上面的結構中。

// ......... 
struct timeval now_tv; 
do_gettimeofday(&now_tv); 
if(!list_empty(&(my_list.time_list))) 
    { 
     tmp = list_first_entry(&(my_list.time_list), struct time_span, time_list); 
     if(tmp != NULL) 
     { 
        tmp->end.tv_sec = now_tv.tv_sec; // THIS BREAKS 
                // Attempting to print "tmp->end.tv_sec" also breaks. 
       tmp->end.tv_usec = now_tv.tv_usec; 
     } 
    } 

根據您提供的信息,我不知道爲什麼上面的內容會打破。也許只是tmp是一個指向垃圾的指針,這就是爲什麼它崩潰?如果您有內核調試器設置,則很容易驗證。

 // ......... 

    if(list_empty(&(my_list.time_list))) 
     { 
     new_time_span = (struct time_span *) kmalloc(sizeof(struct time_span), GFP_KERNEL); 
     INIT_LIST_HEAD(&(new_time_span->time_list)); 
     list_add_tail(&(new_time_span->time_list), &(my_list.time_list)); 
      do_gettimeofday(&(new_time_span->start)); 
    } 

    // ........ 

這裏有一些好文章,應該幫助:
http://kernelnewbies.org/FAQ/LinkedLists
http://sumanadak.blogspot.com/2006/09/linux-kernel-linked-list.html