0

Linux カーネル コードの作成に初めて取り組んでいるのですが、奇妙なカーネル パニックに陥っています。

カーネルの組み込みマクロ (include/linux/list.h) で維持しているリンク リストがあります。リストが空の場合、次の構造のインスタンスを割り当てます。

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

「tmp」というポインターでそれを指します。list_add_tail() で維持しているリストに tmp を追加します。

後で、リストが空でない場合 (デバッグを簡単にするために 1 つのリスト項目でテストしようとしています)、tmp でリストの最初の項目をポイントし、tmp->end.tv_sec の内容を出力しようとします。残念ながら、これによりカーネル パニックが発生します。

tmp は NULL ではなく (実行時にチェックします)、「tmp->end」でもありません (両方を出力できます)。カーネル パニックが発生するのは、"end" のフィールドの 1 つにアクセスしようとしたときだけです。私はこれまでにこのようなものを見たことがありません - 誰か何かアイデアを持っていますか?

ご協力ありがとうございます。

- - - -編集 - - -

コード例 (これは、繰り返し呼び出される関数内にあります):

// .........
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 のリンクされたリストを使用する場合、リストが必要な構造体の中に構造体 list_head を配置する必要があります。
以下のコードでは、型を割り当て、割り当てられた変数内で名前がstruct time_span付けられた変数を参照していますが、それを上記の構造体に追加していません。time_listnew_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 に答える