関数がポインタを受け取った場合 ユーザー空間データには、 copy_from_user()
を使用する必要があります ポイント先のデータをユーザー空間からカーネル空間にコピーします (逆も同様です)。
ポインター値自体は (すべての C パラメーターと同様に) 値渡しされるため、copy_from_user()
を実行する必要がないことに注意してください。 copy_from_user()
する前にポインター値を取得する
数値引数はポインター引数と同じように機能します。 C の用語では、どちらもスカラーです。 copy_from_user()
を使用する必要はありません パラメータの値をコピーします。それはすでにコピーされています。渡されたポインターが指すデータをコピーするためにのみ使用する必要があります。
したがって、タイプ int
のパラメーターがある場合 、直接使用できます。パラメータが int
を指している場合 、次に int
オブジェクトはユーザー空間にあり、 copy_to_user
を使用する必要があります そのオブジェクトの値をカーネル空間にコピーします。
ユーザーがデータをカーネル スペースに渡すと、このデータは複数のページに分割され、これらのページはスワップ アウト メモリにさえ存在する可能性があります。 .これらの場合、カーネルがページにスワップインし、データがあるページにアクセスできるようになるまで待つ必要があります。基本データ型 (int やポインターなど) の場合、一部のアーキテクチャが(特に x86 Intel) ユーザーにデータの整列を強制しないでください。そのため、整数であってもページ境界で分割できます。整数の最初の部分にアクセスできますが、全体にアクセスする前に、2 番目の部分がメモリ マネージャーによってスワップインされるのを待つ必要があります。
ポインターがカーネルに渡される構造体にすべてのユーザー データを配置することで、いくつかのラウンドトリップを節約できます。それをブロックとして copy_from_user し、アクセスを保存できます (そして、数回ブロックされるリスクがあります)
したがって、結論として、基本型にも関数を使用してください 、たくさんあるので。カーネル モードで実行しているときにユーザー データがどこにあるかについて、何も想定しないでください。アクセスできますが、ユーザー データのカーネル仮想アドレスは、ユーザー モードで見られる仮想アドレスとは何の関係もありません。