2009-12-13 105 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