我在编写一些Linux内核代码时遇到了第一次破解,而且我遇到了一个奇怪的内核恐慌。
我有一个链接列表,我正在使用内核的内置宏(include / linux / list.h)进行维护。如果列表为空,我将分配以下结构的实例:
struct time_span
{
struct timeval start;
struct timeval end;
};
并用一个名为“tmp”的指针指向它。我将tmp添加到我正在使用list_add_tail()维护的列表中。
稍后,如果列表不为空(我正在尝试使用一个列表项来测试以简化调试),我指向列表中的第一个项目,使用tmp并尝试打印出tmp->的内容。 end.tv_sec。不幸的是,这会引起内核恐慌。
tmp不是NULL(我在运行时检查),也不是“tmp-> end”(我可以打印两者)。只有当我尝试访问“end”中的一个字段时才会出现内核恐慌。我以前从未见过这样的事情 - 有没有人有任何想法?
感谢您的帮助!
------- ------ EDIT
代码示例(它存在于将被重复调用的函数中):
// .........
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));
}
// ........
答案 0 :(得分: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链接列表时,您应该将struct list_head放在您想要列表的struct中。
在下面的代码中,您正在分配类型struct time_span
并在已分配的变量time_list
中引用名为new_time_span
的变量...但您尚未将其添加到上面的结构中。
// .........
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