3

struct timer_list条件によっては、カスタムデータを処理するタイマー()をスケジュールしたいと思います。この構造のfunctionフィールドは、トリガーされる実際の関数を保持し、次のように定義されます。

void (*function)(unsigned long);

問題は、の代わりにポインタを渡したいということですunsigned long。アーキテクチャによっては、int-ptr変換が安全な場合と安全でない場合があることは知っていますが、すべてのアーキテクチャがlong整数をポインタに揃えているかどうかを見つけることができなかったので、ここに私の質問があります(実際にはツーインワン):

キャストlongするのは安全ですか?いいえの場合、タイマー関数で必要なデータポインターを取得するために、引数をvoid*どのように処理する必要がありますか?unsigned long

4

3 に答える 3

8

Linuxカーネル4.15はデータフィールドを完全に削除し、ここでの回答を廃止しました。私が推測したことから、タイマーコールバックに引数を渡すための好ましい方法は、タイマーと一緒に構造体でそれらを囲み、from_timerマクロを使用してそれらを取得することです。これは次のように定義されます。

#define from_timer(var, callback_timer, timer_fieldname) \
    container_of(callback_timer, typeof(*var), timer_fieldname) 

したがって、引数を渡すために、追加の構造体を次のように定義します。

struct timer_data {
    struct timer_list timer;
    datatype data;
};

セットアップ機能に渡します

struct timer_data *tmd = init_timer_data(); //your logic for init
timer_setup(&tmd->timer, callback, flags);

後で、を使用しfrom_timerて引数を取得します。デフォルトでは、timer_listへのポインターは、unsigned long data4.15より前のバージョンではなく、コールバック関数に渡されます。

void callback(struct timer_list *t) {
    struct timer_data *tmd = from_timer(tmd, t, timer);
    datatype data = tmd -> data;
}
于 2018-05-02T19:46:33.063 に答える
5

タイマー関数の場合やその他の状況では、データ構造体へのポインターをにキャストし、のフィールドに格納して、タイマー関数の引数をデータ構造体へのポインターにキャストすることができます。これは一般的な方法のようです。unsigned longdatastruct timer_list

Linuxドライバー開発、第3回。ed。第7章でその問題について次のように述べています。

引数で複数の項目を渡す必要がある場合は、それらを単一のデータ構造としてバンドルし、unsigned longにキャストされたポインターを渡すことができます。これは、サポートされているすべてのアーキテクチャーで安全な方法であり、メモリ管理ではかなり一般的です(第15章で説明)。

カーネルにはこれの多くの例があります。たとえば、ext4ファイルシステムモジュールのs_err_reportタイマーを参照してください。上記のように、へのポインタがstruct super_blockタイマー関数に渡され、キャストunsigned longとバックが行われます。

于 2013-02-19T15:15:28.820 に答える
2

渡された数値を使用して、カスタムデータ構造を含む配列へのインデックスを作成できます。

于 2013-02-19T09:23:34.330 に答える