Linuxioctl
の定義と互換性レイヤーは、私が頭を悩ませたばかりの魅力的なトピックです。
通常ioctl
、定義では、引数のタイプ名を参照として使用するマクロのファミリー_IOW / _IOR et alと、ioctl引数値を提供するために変更されたマジックナンバーと序数を使用します(例HIDIOCGRAWINFO
)。タイプ名は、定義にエンコードするために使用されsizeof(arg_type)
ます。これは、ユーザースペースで使用されるタイプによって、マクロによって生成される値ioctl
が決まることを意味します。つまり、HIDIOCGRAWINFOは、インクルード条件に基づいて変化する可能性があります。
これが32ビットと64ビットが異なる最初のポイントです。sizeof
パッキングによっては、あいまいなデータサイズ(長いなど)の使用が異なる場合がありますが、特に(そして不可避的に)ポインタ引数を使用する場合は異なります。したがって、この場合、32ビットクライアントをサポートする必要がある64ビットカーネルモジュールは、互換性引数タイプを定義して、引数タイプと同等の32ビットのレイアウトと一致するようにします。したがって、32ビット互換ioctlを定義します。これらの32ビットの同等の定義は、と呼ばれるカーネル機能/レイヤーを利用しますcompat
。
あなたの場合、sizeof()
それはあなたがたどっている道ではないので同じです-しかし、起こっている可能性のあることの全体を理解することは重要です。
さらに、カーネル構成は、32ビットおよび64ビットをサポートする負担を軽減するためCONFIG_COMPAT
にsys-callラッパー(特にユーザー/カーネルインターフェイスwrtを囲むコード)を変更するものを定義する場合があります。ioctl
この一部には、と呼ばれる互換性ioctl
コールバックが含まれioctl_compat
ます。
私が見たのはCONFIG_COMPAT
、32ビットプログラムが64ビットと同じ値を生成できる場合でも(たとえば、あなたの場合)、コールバックにioctl
sを配信するコードを生成することを定義したものです。したがって、ドライバーライターは、特別な(異なる)32ビット互換タイプと通常の「64ビットまたは変更されていない32ビット」タイプの両方を処理することを確認する必要があります。ioctl_compat
ioctl
ioctl_compat
ioctl
したがって、32ビットのみおよび64ビットのみのシステム(CONFIG_COMPATなし)で設計およびテストされたカーネルモジュールは、32ビットおよび64ビットのプログラムでは機能しますが、両方をサポートするプログラムでは機能しません。
したがって、HIDを見ると、これは2.6.38で追加されたことがわかります。
http://lxr.linux.no/#linux+v2.6.38/drivers/hid/hidraw.c#L347