Использование структуры вызывает панику ядра?

Я делаю свою первую попытку написать код ядра 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» (я могу распечатать оба). Только когда я пытаюсь получить доступ к одному из полей в «конце», я получаю панику ядра. Я никогда не видел ничего подобного раньше, у кого-нибудь есть идеи?

Спасибо за любую помощь!

-------РЕДАКТИРОВАТЬ------

Пример кода (это находится в функции, которая будет вызываться неоднократно):

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

    // ........

person zslayton    schedule 13.12.2009    source источник
comment
Опубликуйте код, который иллюстрирует проблему.   -  person    schedule 13.12.2009
comment
В частности, код доступа к полям на tmp->end (и код вокруг него).   -  person T.J. Crowder    schedule 13.12.2009
comment
Вы проверяете адрес структуры при вводе в список и при выходе из списка? Правильно ли инициализирован my_list.time_list?   -  person Tony van der Peet    schedule 13.12.2009
comment
Да -- я проверяю значение адреса new_time_span и адрес tmp, когда вытаскиваю его из списка. Они кажутся одинаковыми. Я вызываю макрос инициализации по адресу головы списка, поэтому я надеюсь, что он делает то, что мне нужно.   -  person zslayton    schedule 13.12.2009


Ответы (1)


Вам не хватает некоторых основ связанных списков Linux. Должно измениться следующее:

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

To:

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

person Steve Lazaridis    schedule 31.12.2009