06
の実装 アーキテクチャに大きく依存しています。
x86 および x86-64 では、ユーザー空間アドレスから直接読み取り、カーネル空間アドレスに書き込むだけで、SMAP (スーパーバイザー モード アクセス防止) が構成されている場合は一時的に無効になります。そのトリッキーな部分は、16
コードは特別な領域に配置されるため、ページ フォールト ハンドラーはその中でフォールトが発生したことを認識できます。 23
で発生するメモリ保護違反 他のプロセスコンテキストコードによってトリガーされた場合のようにプロセスを強制終了したり、割り込みコンテキストで発生した場合のようにカーネルをパニックにしたりしません。 37<を返すコードパスで実行を再開するだけです。 /コード>
「カーネルはカーネル空間アドレスを渡しているので、copy_to_user はどうすればよいですか?ユーザー空間プロセスはどのようにそれにアクセスできますか?」
ユーザー空間プロセスは、任意のアドレスへのアクセスを試みることができます。ただし、アドレスがそのプロセスのユーザー空間 (つまり、そのプロセスのページ テーブル) にマップされていない場合、または読み取り専用の場所への書き込み試行などのアクセスに問題がある場合は、ページ フォールトが生成されます。少なくとも x86 では、すべてのプロセスのすべてのカーネル空間がそのプロセスの仮想アドレス空間の最下位 1 ギガバイトにマップされていることに注意してください。ユーザー空間へのコピー、またはユーザー空間からのコピーは、プロセスに代わって実行されているカーネル コードによって実行され、実際にはそのプロセスのメモリ マッピング (ページ テーブル) です。コピー中に使用中のもの。これは、実行がカーネル モード (x86 言語の特権/スーパーバイザー モード) で行われている間に行われます。ユーザー空間コードが正当なターゲットの場所 (つまり、そのプロセス アドレス空間に適切にマップされたアドレス) を渡して、データを copy_to_user にコピーしたと仮定します。 、カーネルコンテキストから実行すると、通常は問題なくそのアドレス/領域に書き込むことができ、制御がユーザーに戻った後、ユーザー空間もプロセス自体によってこの場所の設定から読み取ることができます。さらに興味深い詳細はLinux カーネルの理解、第 3 版、Daniel P. Bovet、Marco Cesati の第 9 章と第 10 章にあります。特に、access_ok() は必要ですが、十分ではありません。ユーザーは、プロセスのアドレス空間に属さないアドレスを渡すことができます。この場合、カーネル コードがコピーを実行している間にページ フォールト例外が発生します。最も興味深い部分は、カーネル ページ フォールト ハンドラーが、そのような場合のページ フォールトがカーネル コードのバグによるものではなく、ユーザーからの不適切なアドレスによるものであると判断する方法です (特に問題のカーネル コードがカーネル モジュールからのものである場合)。ロード済み)