これは特定のOSに関する質問ではありませんが、Windowsを例にしましょう。ユーザー空間プログラムは、Windows APIを使用してkernelspaceと通信します。しかし、私はそれがいかに可能か理解していません。 MSのウェブサイトによると、APIはユーザー空間に存在します。カーネル空間にアクセスするためには、正しく理解すればカーネル空間内になければなりません。だから、Windows APIがカーネル空間に話す特別な特権を得る仕組みは何ですか?そのメカニズムはどの空間で動作しますか?現代のすべてのPC OSにこの種のものが普遍的ですか?オペレーティングシステムは、ユーザー空間プログラムがカーネル空間プログラムとやりとりすることを可能にしますか?
答えて
CPUは、ユーザメモリ空間(ユーザモードでアクセス可能)と保護されたメモリ空間(カーネルモードでアクセス可能)との間の情報転送の中間としてCPUレジスタを介して動作します。ここで
は例です:
ユーザーは、より高いレベルの言語でプログラムを書きとします。プログラムの実行が行われると、CPUは仮想アドレスを生成します。
読み書き操作が行われる前に、仮想アドレスは物理アドレスに変換されます。変換機構(メモリ管理ユニット)はカーネルモードでのみアクセス可能であり、保護されたメモリに格納されるため、変換はカーネルモードで行われ、物理アドレスは最終的にCPUのレジスタに保存され、書き込み動作が発生する。
私は参照してください。しかし、コミュニケーションはどうやって他の方法になりますか?私は、カーネル空間プログラムがユーザー空間に戻って通信できることを知っています。レジスタは保護されていませんか?何も利用できない場合はどうなりますか? –
汎用レジスタは保護されておらず、使用するプログラム用です。実際、OSがタスクを切り替えるたびに、古いタスクのレジスタが保存され、新しいタスクのレジスタが復元されます。さらに、プログラムにレジスタを使用させないようにしても、あるメモリ位置から別のメモリ位置に値を移動することはできません( 'mov [loc2]、[loc1]'は無効です)。ほぼすべての操作のためにメモリにアクセスする)。 – glauxosdever
この回答は、使用されている実際のシステムコールメカニズムを見落としており、レジスタやMMUの動作を使用してデータの転送を説明することはあまり正確ではありません。 – Flexo
既に知っているように、Windowsカーネルによってユーザー空間プログラムに公開されている多数の機能があります。 (あなたが好奇心なら、there's a list of system calls)。これらのシステムコールはすべて一意の番号で識別されますが、これはMicrosoftが公開している公開されているインターフェイスの一部ではありません。代わりに、あなたのプログラムから公開されている関数を呼び出すときには、通常の特権のないユーザーモード関数呼び出しであるエントリポイントを持つWindowsをインストール(または更新)するとDLLがインストールされます。このDLLは、現在実行中のカーネルでパブリックインターフェイスと使用可能なシステムコールの間のマッピングを認識します。これらのマッピングは常に1:1であるとは限らず、安定したインターフェイスを使用して既存のコードを破ることなく調整や拡張が可能です。
ユーザランドコードによっては、これらの関数のうちの1つを呼び出すときに、その役割はシステムコールの引数を準備してカーネルモードにジャンプすることです。ジャンプがどのくらい正確に発生するかは、Windowsが現在実行しているアーキテクチャに固有です。実際、それはx86とArmの間だけでなく、AMDとIntel x86システムの間でも変わります。ここでは、簡潔にするために、最新のIntel x86 32ビット・ケース(SYSENTER instructionを使用)について説明します。 x86では、他のバリエーションのほとんどは比較的小さなものです。たとえばint 2Eh
was used prior to SYSENTER supportです。
起動時にオペレーティングシステムは、ユーザーランドとシステムコールを有効にするための準備作業を行います。これを理解することは、システムコールの実際の動作を理解するうえで重要です。
まず、少し巻き戻して、ユーザーランドとカーネルモードが何を意味するのかを考えてみましょう。 x86では、特権コードと特権コードについて、「リング」について話します。実際には4つあります(ハイパーバイザーは無視します)が、ring0(カーネル)とring3(ユーザーランド)以外は何も使用しませんでした。 x86上でコードを実行するとき、実行されているアドレス(EIP)と読み書き中のデータはセグメントから来ます。
セグメントは、ほとんどの場合、x86上の仮想アドレス指定が問題であった頃から残された歴史的な事故です。ただし、命令やその他の参照メモリを実行するときに現在どのセグメントが使用されているかを定義する特別なレジスタがあるため、これらは重要です。 x86上のセグメントは、すべてグローバルディスクリプタテーブルまたはGDTと呼ばれる大きなテーブルに定義されています。(ローカルデスクリプタテーブル、LDTもありますが、ここではこれ以上説明しません)。ここで議論する重要なポイントは、テーブルエントリの(秘密の)レイアウトには、現在アクティブなセグメントの特権レベルを定義するDPLという2ビットが含まれていることです。 2ビットが正確に4レベルの特権を定義するのに十分であることに気付くでしょう。
「カーネルモードで実行する」と言いますと、実際にはアクティブなコードセグメント(CS)とデータセグメントセレクタがDPLを0に設定したGDTのエントリを指しているだけです。 DPLが3に設定され、カーネルアドレスへのアクセスがない状態で、GDTエントリを指し示すCSセグメントおよびデータセグメントセレクタを有する。 (他のセレクタもありますが、シンプルにするために、今は "コード"と "データ"を考慮します)。
カーネルの起動時に最初に戻る:起動時にカーネルはGDT entries we needを作成します。 (これらは、SYSENTERが動作するためには特定の順序で配置する必要がありますが、ほとんどは実装の詳細です)。また、プロセッサの動作を制御する「マシン固有のレジスタ」もあります。これらは特権コードによってのみ設定できます。ここで重要なそれらのうち3つは、次のとおりです。
- IA32_SYSENTER_ESP我々はリング0に移行したいユーザランド(RING3)にrunnigいくつかのコードを持っている
- IA32_SYSENTER_EIP
- IA32_SYSENTER_CS
リコール。呼び出し規約で必要とするレジスタをすべて保存し、呼び出しに必要な正しいレジスタに引数を格納すると仮定しましょう。その後、SYSENTER命令を実行します。 (実際はKiFastSystemCall
と思う)。 SYSENTER命令は特殊です。これは、マシン固有のレジスタIA32_SYSENTER_CSのカーネル設定値に基づいて、現在のコードおよびデータセグメントセレクタを変更します。 (スタック/データセグメント値はIA32_SYSENTER_CSのオフセットとして計算されます)。その後、スタックポインタ自体(ESP)は、以前にシステムコールを処理するために設定されたカーネルスタックに設定され、MSR IA32_SYSENTER_ESPに保存され、IA32_SYSENTER_EIPからの命令ポインタも同様にEIPに格納されます。
DPLが0に設定された状態でCSセレクタがGDTエントリを指すようになり、EIPはこの時点でカーネルで実行しているカーネルスタック上のカーネルモードコードを指しています。
ここから、カーネルモードコードは、システムコールの実行に必要な実際の作業を行うために、カーネルとユーザースペースの両方からメモリを読み書きできます(適切な注意が必要です)。システムコールへの引数は呼び出し規約に従ってレジスタなどから読み取ることができますが、実際にはユーザランドに戻るポインタやカーネルオブジェクトのハンドルにアクセスして、大きなデータブロックを読み取ることもできます。
システムコールが終了すると、プロセスは基本的に逆になり、セレクタのDPL 3でuserlandに戻ります。
- 1. Linuxユーザー空間とカーネル空間スケジューリング
- 2. ユーザ空間とカーネル空間の間でメモリを共有する
- 3. linuxカーネル空間のユーザー空間スタックトレースを表示するには
- 4. カーネル空間とユーザ空間の時間の差異
- 5. カーネル空間からユーザ空間にパケットをバイパスする
- 6. Linuxカーネルがユーザー空間と通信できる方法は何ですか?
- 7. malloc()はカーネル空間にありますか?
- 8. sysを使ってカーネルとユーザー空間の間でメモリを共有する
- 9. Linuxカーネルからユーザー空間のメモリにアクセスするには?
- 10. copy_to_userがカーネルからmmapユーザーにデータをコピーできませんでしたか?ユーザ空間プログラムの開発で
- 11. カーネルモジュールからユーザー空間プログラムを強制終了する
- 12. 他のプログラムとやりとりするプログラムを書く方法
- 13. ユーザーが一定期間プログラムとやりとりすることを制限するにはどうすればよいですか?
- 14. カーネル空間でシステムコールを呼び出すことはできますか?
- 15. カーネルとユーザー空間の間に「ネットリンク」を作成するにはどうすればよいですか?
- 16. KLMとユーザー空間のファイル
- 17. `round`を名前空間stdに入れることは可能ですか?
- 18. Linuxカーネルのユーザー空間ライブラリmodal - テスト用
- 19. Rtree空間インデックスを酸洗することは可能ですか?
- 20. ユーザー空間とカーネルスレッド間の共有メモリ
- 21. std :: threadsはユーザ空間またはカーネル空間で管理されますか?
- 22. .textデータセグメントと.finiデータセグメントの間に空白がありますか?
- 23. 画像処理 - カーネル空間、関数、データとは何ですか?
- 24. netlinkソケットを使用してLinuxカーネルのユーザー空間アプリケーションと文字デバイス間で通信するときのエラー
- 25. ユーザ空間プログラムでカーネルlibcrc32c(または同じ機能)を使用するには?
- 26. 、Linuxではカーネル空間
- 27. ウェブとやり取りするプログラム
- 28. Kubernetes。ユーザーのためにデフォルト名前空間を構成することは可能ですか?
- 29. カーネル空間から返された構造体をユーザ空間にコピーすることは不可欠ですか?
- 30. カーネル空間からユーザ空間関数を実行
"システムコール"を参照してください。 – glauxosdever
こんにちは、私はメカニズムが*システムコールと呼ばれていることを知っています。私の質問は、オペレーティングシステムが情報を2つのメモリ空間の間でどのように転送するかについてです。システムコールはおそらく関数であり、おそらくユーザ空間で動作するプログラムにコンパイルされます。それはカーネル空間にアクセスすべきではありません。それはなぜですか?例えば中間の3番目のスペースはありますか? –
@MichaelStachowsky質問があればお気軽に。 –