0

我第一次尝试编写一些 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”中的某个字段时,我才会出现内核恐慌。我以前从未见过这样的事情——有人有什么想法吗?

感谢您的帮助!

- - - -编辑 - - -

代码示例(这存在于将被重复调用的函数中):

// .........
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));
    }

    // ........
4

1 回答 1

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 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

于 2009-12-31T17:37:47.477 回答