Linuxカーネルregister_chdevの戻り値

Linuxカーネルregister_chdevの戻り値

このビデオは、新しいキャラクタ デバイスを作成する Raspberry Pi Linux カーネル モジュールの例を示しています。カーネル API を使用します。ビデオへのコメント (直接リンクを生成することはできません) で、 の戻り値に関して、著者は次のように述べていますregister_chdevregister_chdev

戻り値が 0 でない場合、デバイス番号はすでに使用されています。戻り値の上位 12 ビットはメジャー デバイス番号で、下位 20 ビットはマイナー デバイス番号です。

「デバイス番号はすでに使用されています」とは、「カーネル モジュールで任意に選択された 0 以外のメジャー デバイス番号がすでに使用されています」という意味だと思います。

これについてはいくつかのウェブページが取り上げているが(公式のもの、 それからこれですそしてこれです)、戻り値のこの内部細分化に関する情報は見つかりませんでした。

すでに使用されているメジャー番号を持つデバイスを(カーネル モジュールを使用して)作成することを選択した場合、カーネルはそれを決して受け入れず、デバイスの登録を拒否します。 これは、選択したメジャー番号がブロック デバイスのメジャー番号と同じ場合と、選択したメジャー番号がキャラクタ デバイスのメジャー番号と同じ場合の両方で発生します。register_chdev常に負の値を返します。 後者の場合、代わりに、上位 12 ビットがメジャー デバイス番号を表し、下位 20 ビットがマイナー デバイス番号を表す、ゼロ以外の正の戻り値を期待していました(0 より大きい可能性があります。メジャー番号がすでに使用されている場合、システムには少なくともマイナー番号 0 のそれに関連するデバイスがすでに存在している可能性があります)。

YouTube のコメントに書かれていることは本当ですか? それに関する資料はどこで見つかりますか?


Raspbian 10 を実行していますが、次のuname -aように表示されます:

Linux raspberrypi 5.10.63-v7+ #1459 SMP Wed Oct 6 16:41:10 BST 2021 armv7l GNU/Linux

答え1

register_chrdevカーネルには文書化されていないが、その定義は短い:

static inline int register_chrdev(unsigned int major, const char *name,
                  const struct file_operations *fops)
{
    return __register_chrdev(major, 0, 256, name, fops);
}

つまり、基本的には__register_chrdevメジャーをマイナーの全範囲(0から始まる256のマイナー)で登録し、その関数の結果を返します。後者は次のように文書化されています。

もしmajor== 0 この関数はメジャーを動的に割り当て、その番号を返します。

もしmajor> 0 の場合、この関数は指定されたメジャー番号でデバイスを予約しようとし、成功した場合は 0 を返します。

失敗した場合は -ve errno を返します。

エンコードされているかどうかに関係なく、マイナーを返すための規定はありません。これらの関数の目的は、単一のマイナーではなく、マイナーのサブセットを含む可能性のあるメジャーを登録することです。

エンコーディングデバイスドライバがopen呼び出しを処理するとき、または特定のデバイスがどのマイナー(および複数のメジャーを処理する場合はメジャー)に対応するかを判断する必要があるときに機能します。ドライバには、処理するように要求されたinodeが与えられます。デバイスノードの場合、これにはメジャーとマイナーをエンコードしたデバイス番号が含まれます。MAJORそしてMINORマクロ、またはinodeから開始して、imajorそしてiminor関数を使用して値を抽出する必要もあります。

一部のキャラクタデバイスでは、上記の主要な登録メカニズムに加えて多重化機能も提供しています。1 つのさまざまなドライバーがどのようにしてこれらすべての異なるハードウェアを制御するのでしょうか?この例についてはこちらをご覧ください。

関連情報