オペレーティング システムのインタビュー関連の知識

目次

1. はじめに

1. オペレーティングシステムとは何ですか

オペレーティングシステムはカーネル状態で動作するソフトウェアであると言えます。
アプリケーションとハードウェアの間の仲介者として機能し、アプリケーションにハードウェアの抽象化を提供し、ハードウェア リソースを管理します。
ここに画像の説明を挿入

2. オペレーティング システムの主な機能は何ですか?

オペレーティング システムの主な機能:

プロセッサ (CPU) 管理: CPU の管理と割り当て。主にプロセス管理を指します。
メモリ管理: メモリの割り当てと管理には、主に仮想メモリの方法が使用されます。
外部メモリ管理: 外部メモリ (ディスクなど) の割り当てと管理。外部メモリをファイルの形式で提供します。
I/O管理:入出力デバイスを一元管理。
さらに、正常に動作するための堅牢性管理や、不正な操作や侵入を防ぐためのセキュリティ管理もあります。
ここに画像の説明を挿入

第二に、オペレーティング システムの構造

1. カーネルとは何ですか?

カーネルは、オペレーティング システムの中核であり、オペレーティング システムの中核機能を提供し、オペレーティング システム内のすべてのコンテンツを制御できるコンピューター プログラムであると言えます。

2. ユーザーモードとカーネルモードとは何ですか?

カーネルは非常に高い権限を持ち、CPU、メモリ、ハードディスクなどのハードウェアを制御することができますが、ほとんどのオペレーティングシステムでは権限制御のためにメモリを次の2つの領域に分割しています。

  • カーネル空間。このメモリ空間にはカーネル プログラムのみがアクセスできます。
  • ユーザー空間。このメモリ空間はアプリケーション専用であり、アクセス許可は比較的小さいです。

ユーザー空間のコードはローカル メモリ空間にのみアクセスできますが、カーネル空間のコードはすべてのメモリ空間にアクセスできます。したがって、プログラムがユーザー空間を使用する場合、プログラムはユーザー モードで実行され、プログラムがカーネル空間を使用する場合、プログラムはカーネル モードで実行されるとよく​​言われます。

3. ユーザーモードとカーネルモードを切り替えるにはどうすればよいですか?

アプリケーションがカーネル空間に入る必要がある場合、システム コールを通じてカーネル モードに入る必要があります。カーネル プログラムは
ここに画像の説明を挿入
カーネル モードで実行され、ユーザー プログラムはユーザー モードで実行されます。アプリケーションがシステムコールを使用すると、割り込みが発生します。割り込みが発生すると、CPU は現在実行中のユーザー プログラムを中断し、割り込みハンドラーにジャンプし、カーネル プログラムの実行を開始します。カーネルは処理を終了すると、積極的に割り込みをトリガーし、CPU の実行権限をユーザー プログラムに返し、ユーザー状態に戻って作業を継続します。

3. プロセスとスレッド

1. 並列処理と同時実行の違いは何ですか?

同時実行性とは、一定期間内に複数のタスクが処理されるが、ある時点では 1 つのタスクのみが実行されることを意味します。シングルコア プロセッサによって実現される同時実行性は、実際にはタイム スライスのローテーションです。たとえば、2 つのプロセス A と B があります。A がタイム スライスを実行した後、B に切り替わり、B がタイム スライスを実行してから、B に切り替わります。 A. 切り替え速度が十分に速いため、複数のプログラムを一定期間同時に実行できることが巨視的に示されています。

並列処理とは、複数のタスクが同時に実行されることを意味します。これを完了するにはマルチコア プロセッサが必要です。マイクロ レベルでは、複数の命令を同時に実行できます。異なるプログラムは異なるプロセッサ上で実行されます。これは、物理的には同時に複数のプロセスです。
ここに画像の説明を挿入

2. プロセスコンテキストスイッチングとは何ですか?

シングルコアシングルスレッド CPU の場合、一度に実行できる CPU 命令は 1 つだけです。コンテキストスイッチ(Context Switch)とは、あるプロセスから別のプロセスにCPUリソースを割り当てる仕組みです。ユーザーの観点から見ると、コンピューターは複数のプロセスを並行して実行できます。これはまさに、オペレーティング システムによる高速なコンテキスト スイッチングの結果です。切り替えのプロセスでは、オペレーティング システムは現在のプロセスの状態 (メモリ空間のポインタ、現在実行されている命令などを含む) を保存し、次のプロセスの状態を読み取って実行する必要があります。プロセス。
ここに画像の説明を挿入

3. プロセスの状態は何ですか?

プロセスが実行を開始すると、次の状態を経る可能性があります。

上図の各状態の意味は次のとおりです。

実行状態 (Running): プロセスが現時点で CPU を占有している;
準備完了状態 (Ready): 実行可能だが、他のプロセスが実行中であるため一時的に実行が停止している;
ブロック状態 (Blocked): プロセスが特定のイベントの発生を待機している(入出力処理の完了待ちなど)一時的に動作を停止しますが、このときCPUに制御を渡されても動作しません。
ここに画像の説明を挿入

もちろん、プロセスには他に 2 つの基本的な状態があります。

作成状態 (new): プロセスが作成されるときの状態、
終了状態 (Exit): プロセスがシステムから消滅するときの状態。
ここに画像の説明を挿入

4. ゾンビプロセスとは何ですか?

ゾンビ プロセスは、完了して終了状態にあるものの、プロセス テーブルにまだ存在しているプロセスです。

ゾンビプロセスは通常、親子関係にあるプロセス内で発生します。子プロセスのプロセス記述子は、子プロセスが終了しても解放されません。親プロセスがwait()またはwaitpidによって子プロセスの情報を取得した場合にのみ解放されます。 ()。親プロセスで wait() または waitpid() を呼び出さずに子プロセスが終了した場合でも、子プロセスのプロセス記述子はシステムに保存されたままになります。

5. 孤立プロセスとは何ですか?

親プロセスが終了し、その 1 つ以上の子プロセスがまだ実行中の場合、これらの子プロセスは孤立したプロセスになります。孤立プロセスは init プロセス (プロセス ID が 1 のプロセス) によって採用され、init プロセスはそれらの状態収集作業を完了します。孤立したプロセスは init プロセスによって採用されるため、孤立したプロセスはシステムに悪影響を及ぼしません。

6. プロセスのスケジューリング アルゴリズムは何ですか?

プロセス スケジューリングは、特定の瞬間に CPU がどのプロセスを実行するかを決定することです。一般的なプロセス スケジューリング アルゴリズムには次のものがあります。

ここに画像の説明を挿入

  • 先着順の
    非プリエンプティブ スケジューリング アルゴリズム。リクエストの順序に従ってスケジューリングします。これは長いジョブには適していますが、短いジョブには適していません。短いジョブは、前の長いジョブが実行されるまで待機してから実行する必要があり、長いジョブは長時間実行する必要があるため、結果として次のような結果が得られます。短い仕事の待ち時間が長すぎる。さらに、このようなプロセスは各 I/O 操作の後に再度キューに入れる必要があるため、I/O 集中型のプロセスには適していません。
    ここに画像の説明を挿入
  • 最短のジョブを優先
    推定実行時間の短い順にスケジュールを設定する、非プリエンプティブ スケジューリング アルゴリズム。長いジョブは餓死する可能性があり、短いジョブが終了するのを待っている状態になります。短いジョブが次々に来ると、長いジョブは決してスケジュールされないからです。
    ここに画像の説明を挿入
  • 優先スケジューリング
    各プロセスに優先度を割り当て、優先度に従ってスケジュールを設定します。優先度の低いプロセスがスケジュールされるまで待機しないようにするために、待機しているプロセスの優先度を時間の経過とともに高めることができます。
    ここに画像の説明を挿入
  • タイムスライスの回転

先着順の原則に従って、準備が完了したすべてのプロセスをキューに配置し、スケジュールされるたびにキュー リーダー プロセスに CPU 時間を割り当てます。このプロセスはタイム スライスを実行できます。タイム スライスが使い果たされると、タイマーはクロック割り込みを送信し、スケジューラはプロセスの実行を停止してレディ キューの最後に送信し、キューの先頭にあるプロセスに CPU 時間を割り当て続けます。 。

タイム スライス ローテーション アルゴリズムの効率は、タイム スライスのサイズに大きく関係します。プロセスの切り替えではプロセス情報を保存し、新しいプロセスの情報を読み込む必要があるため、タイム スライスが小さすぎる場合、プロセスの切り替えは頻度が多すぎると時間がかかりすぎます。また、タイム スライスが長すぎる場合、リアルタイムのパフォーマンスは保証されません。
ここに画像の説明を挿入

  • 最短残り時間優先
    残り実行時間の順にスケジュールされた、最短ジョブ優先のプリエンプティブ バージョン。新しいジョブが到着すると、その全体の実行時間が現在のプロセスの残り時間と比較されます。新しいプロセスに必要な時間が短い場合は、現在のプロセスを一時停止して、新しいプロセスを実行します。それ以外の場合、新しいプロセスは待機します。

プロセス間通信にはどのような方法があるのでしょうか?

ここに画像の説明を挿入

  • パイプライン: パイプラインは、異なるプロセス間の対話として理解できます。一方が音を出し、もう一方がそれを受け取ります。音の媒体は空気またはケーブルであり、プロセスはパイプラインを通過できます。いわゆるパイプラインはカーネル内のバッファの文字列 パイプラインから 一方の端での書き込みデータはカーネルにキャッシュされ、もう一方の端での読み取りでは、このデータもカーネルから読み取られます。

  • パイプは、匿名パイプと名前付きパイプの 2 つのカテゴリに分類できます。匿名パイプは一方向であり、関連するプロセス間でのみ通信できます。名前付きパイプは双方向で、マシン上の任意の 2 つのプロセス間で通信できます。

ここに画像の説明を挿入

  • シグナル: シグナルは電文として理解できます。送信者はコンテンツを送信し、受信プロセスを指定して、特定のソフトウェア割り込みを送信します。割り込み要求を受信した後、オペレーティング システムは受信プロセスを見つけて、受信プロセスにメッセージを処理するように通知します。信号。

    たとえば、kill -9 1050 は、PID 1050 のプロセスに SIGKIL シグナルを送信することを意味します。Linux システムで一般的に使用されるシグナル:
    (1) SIGHUP: ユーザーが端末からログアウトすると、開始されたすべてのプロセスがこのプロセスを受け取ります。デフォルトでは、システムはプロセスを終了することによってこの信号を処理します。
    (2) SIGINT: プログラム終了信号。プログラムの実行中に Ctrl+C キーを押すと、この信号が生成されます。(3) SIGQUIT: プログラム終了信号。プログラムの実行中に Ctrl+\ キーを押すと、この信号が生成されます。(4) SIGBUS および SIGSEGV: プロセスが不正なアドレスにアクセスします。
    (5) SIGFPE: ゼロ除算、データオーバーフローなど、演算中に致命的なエラーが発生しました。
    (6) SIGKILL: ユーザーがプロセス実行シグナルを終了します。このシグナルを送信するには、シェルの下で kill -9 を実行します。(7) SIGTERM: プロセス終了信号。このシグナルを送信するには、シェルの下で kill process pid を実行します。
    (8) SIGALRM: タイマー信号。
    (9) SIGCLD: サブプロセス終了信号。親プロセスがシグナルを無視せず、シグナルを処理しない場合、子プロセスは終了後にゾンビプロセスを形成します。

  • メッセージ キュー: メッセージ キューは、Posix メッセージ キューや System V メッセージ キューなど、カーネルに格納されているメッセージのリンク リストです。十分な権限を持つプロセスはキューにメッセージを追加でき、読み取り権限を付与されたプロセスはキューからメッセージを読み取ることができます。メッセージ キューは、信号によって運ばれる情報量が少ないという欠点を克服します。パイプラインはフォーマットされていないバイト ストリームのみを運ぶことができ、バッファ サイズは制限されています。

ここに画像の説明を挿入

  • 共有メモリ: 共有メモリのメカニズムは、仮想アドレス空間の一部を取り出して、それを同じ物理メモリにマップすることです。このようにして、このプロセスによって書き込まれた内容を他のプロセスから直接見ることができます。共有メモリは IPC の最も高速な方法であり、プロセス間通信の他の方法が実行されている場合には非効率的に実行されるように特別に設計されています。多くの場合、プロセス間の同期と通信を実現するために、セマフォなどの他の通信メカニズムと組み合わせて使用​​されます。

ここに画像の説明を挿入

  • セマフォ: セマフォは、信号機、赤信号が進み、青信号が停止するものとして理解できます。これは本質的に、複数のプロセスによる共有リソースへのアクセスを制御するために使用できる整数カウンターです。これは、プロセスがリソースにアクセスしている間、他のプロセスが共有リソースにアクセスできないようにするためのロック メカニズムとしてよく使用されます。したがって、主にプロセス間および同じプロセス内の異なるスレッド間の同期手段として使用されます。

セマフォはリソースの数を表し、セマフォを制御するための 2 つのアトミック操作があります。

1 つは P 操作で、セマフォから 1 を減算します。減算後のセマフォが 0 未満の場合は、リソースが占有されており、プロセスはブロック待機する必要があることを示します。減算後のセマフォ >= 0 の場合は、使用可能なリソースがまだ存在し、プロセスが通常どおり続行できることを示します。

もう 1 つは V 操作です。この操作はセマフォに 1 を追加します。追加後のセマフォ <= 0 の場合は、現在ブロックされているプロセスがあることを示しているため、プロセスは起動して実行されます。追加後、シグナルの量が > 0 の場合、現在ブロックされているプロセスがないことを意味します。
ここに画像の説明を挿入

  • ソケット: 他の通信メカニズムとは異なり、異なるマシン間のプロセス通信に使用できます。

  • 長所と短所:

    パイプライン: シンプル、効率が低く、容量が限られている、
    メッセージ キュー: タイムリーではない、書き込みと読み取りにはユーザー モードとカーネル モードでのコピーが必要です。
    共有メモリ領域: 容量の制御が容易で高速ですが、異なるプロセスの同期に注意する必要があります。
    セマフォ: 複雑なメッセージを送信できず、通常はプロセス間の同期を達成するために使用されます;
    シグナル: プロセス間通信のための唯一の非同期メカニズムです。
    ソケット: 異なるホストプロセス間の通信に使用されます。

7. プロセスとスレッドの関係と違いは何ですか?

スレッドとプロセス間の接続:

スレッドはプロセス内の実行フローです。

同じプロセス内の複数のスレッドは、コード セグメント、データ セグメント、オープン ファイルなどのリソースを共有できますが、各スレッドには独自のレジスタとスタックのセットがあり、スレッドの制御フローが比較的独立していることが保証されます。
ここに画像の説明を挿入
スレッドとプロセスの比較は次のとおりです。

  • スケジューリング: プロセスはリソース割り当て (メモリ、開いているファイルなどを含む) の単位であり、スレッドは CPU スケジューリングの単位です。
  • リソース: プロセスは完全なリソース プラットフォームを備えていますが、スレッドはレジスタやスタックなどの重要なリソースのみを共有します。
  • リソースの所有: スレッドには、準備完了、ブロック済み、実行中の 3 つの基本状態があり、状態間の遷移関係もあります。
  • システム オーバーヘッド: スレッドは、同時実行の時間とスペースのオーバーヘッドを削減できます。プロセスを作成またはキャンセルするとき、システムはメモリ スペース、I/O デバイスなどのシステム リソースを割り当てたり再利用したりする必要があり、オーバーヘッドが発生します。 OS によるオーバーヘッドは、スレッドの作成または取り消し時のオーバーヘッドよりも大幅に大きく、プロセス切り替えのオーバーヘッドもスレッド切り替えのオーバーヘッドよりもはるかに大きくなります。

8. スレッドのコンテキスト切り替えを理解していますか?

また、スレッドが同じプロセスに属しているかどうかによっても異なります。

2 つのスレッドが同じプロセスに属していない場合、切り替えプロセスはプロセス コンテキストの切り替えと同じです。

2つのスレッドが同じプロセスに属する場合、仮想メモリが共有されるため、切り替え時に仮想メモリなどのリソースは変化せず、スレッドのプライベートデータやレジスタなど共有されていないデータのみを切り替えるだけで済みます。

したがって、スレッド コンテキスト切り替えのオーバーヘッドはプロセスのオーバーヘッドよりもはるかに小さくなります。

9. スレッドの実装方法は何ですか?

スレッドを実装するには主に 3 つの方法があります。

  • カーネル モード スレッドの実装: カーネル空間に実装されたスレッドは、カーネルによって直接管理されます。
    ここに画像の説明を挿入
  • ユーザー モード スレッドの実装: ユーザー空間でのスレッドの実装にはカーネルの参加は必要なく、カーネルはスレッドを認識しません。
    ここに画像の説明を挿入
  • ハイブリッド スレッドの実装: 最新のオペレーティング システムでは、基本的に 2 つの方法を組み合わせて使用​​します。ユーザー モード実行システムは、プロセスの内部スレッドがブロックされていない場合の切り替えを担当し、カーネル モード オペレーティング システムはブロックされたスレッドの切り替えを担当します。つまり、カーネル モードとユーザー モードの両方のスレッド管理を実装します。このうち、カーネル モード スレッドの数は少なく、ユーザー モード スレッドの数は多くなります。各カーネル モード スレッドは 1 つ以上のユーザー モード スレッドを処理できます。
    ここに画像の説明を挿入

10. スレッド間で同期するにはどうすればよいですか?

同期は、リソースを共有するマルチスレッド操作の問題を解決します。その目的は、スレッド間の実行がどのように分散していても、最終結果が正しいことを保証することです。

スレッドとプロセスの関係についてはすでに説明しました。スレッドはプロセス内の実行フローです。したがって、次の同期メカニズムの一部はスレッドだけでなくプロセスにも適用されます。

クリティカル セクション: 共有リソースにアクセスするプログラム フラグメントをクリティカル セクションと呼びます。このコードが相互に排他的であり、特定の時間に 1 つのスレッドによってのみ実行できることを望みます。つまり、スレッドがクリティカル セクションで実行されるとき、他のスレッドがクリティカルセクションに入ることをブロックする必要があります。
ここに画像の説明を挿入
クリティカル セクションはスレッドだけでなくプロセスにも含まれます。

クリティカル セクション同期のいくつかの実装:

1.ロック

ロック操作とロック解除操作を使用すると、同時スレッド/プロセスの相互排他問題を解決できます。

クリティカル セクションに入ろうとするスレッドは、まずロック操作を実行する必要があります。ロック操作が成功すると、スレッドはクリティカル セクションに入ることができ、クリティカル リソースへのアクセスが完了した後、ロック解除操作を実行してクリティカル リソースを解放します。

ロックとロック解除とは何ですか? クリティカル セクション オブジェクトまたは単純なミューテックスにすることができます。たとえば、ミューテックスはロックなしでは 0 で、1 はロックを意味します。
ここに画像の説明を挿入
ロックのさまざまな実装に応じて、ロックはビジー待機ロックとビジー待機なしロックに分類できます。

忙等待锁そして、ロックに失敗したスレッドは、スピン ロックとも呼ばれるロックの取得を試み続け、常に CPU を占有します。

⽆忙等待锁つまり、ロックに失敗したスレッドはブロック状態になり、CPU を放棄し、スケジュールされるまで待機します。

2. セマフォ
セマフォは、共有リソースへのアクセスを調整するためにオペレーティング システムによって提供される方法です。

通常、セマフォはリソースの数を表し、対応する変数は整数 (sem) 変数です。

さらに、セマフォを制御するための 2 つのアトミック操作システム コール関数があります。

P 操作: sem を 1 だけデクリメントします。減算後、sem < 0 の場合、プロセス/スレッドはブロッキング待機に入ります。そうでない場合は続行し、P 操作がブロックされる可能性があることを示します。

V 操作: sem に 1 を追加します。追加後、sem <= 0 の場合、待機中のプロセス/スレッドをウェイクアップし、V 操作がブロックされないことを示します。

P 操作はクリティカル セクションに入る前に使用され、V 操作はクリティカル セクションを出た後に使用され、これら 2 つの操作はペアで使用する必要があります。

11. デッドロックとは何ですか?

2 つ以上の同時スレッドで、各スレッドが特定のリソースを保持し、他のスレッドがそのリソースまたは現在保持しているリソースを解放するのを待機している場合、この状態が変更されるまでスレッドは先に進むことができません。平たく言えば、2 つ以上のスレッドが無期限にブロックされ、互いに待機している状態です。
ここに画像の説明を挿入

12. デッドロックが発生する条件は何ですか?

デッドロックが発生するには、次の 4 つの条件が同時に満たされる必要があります。

相互排他条件: 取得したリソースのスレッドによる他の使用を指します。つまり、リソースは同時に 1 つのスレッドによってのみ占有されます。この時点でリソースの取得を要求している他のスレッドがある場合、要求者はリソースを占有しているスレッドがリソースを解放するまで待つことしかできません。
要求および保持条件: 少なくとも 1 つのリソースをすでに保持しているスレッドを指しますが、新しいリソース要求を提案しており、新しいリソースはすでに他のスレッドによって占有されているため、現在のスレッドはブロックされますが、その間は解放されません。ブロックされたリソースはすでに取得されています。
非エイリアン可能条件: スレッドによって取得されたリソースは、使い果たされる前に他のスレッドによってプリエンプトされることができず、リソースは使い切られた後にのみ解放できることを意味します。
ループ待機条件: デッドロックが発生した場合、スレッドが存在する必要があります。リソースの循環チェーン、つまり、スレッド コレクション {T0, T1, T2,..., Tn} 内の T0 は、T1 が占有するリソースを待機しています。 、Tl1 は T1 によって占有されているリソースを待機中、T2 によって使用されているリソースを待機中、...Tn はすでに T0 によって占有されているリソースを待機しています。

13. デッドロックを回避するにはどうすればよいですか?

デッドロックが発生するために必要な条件は、相互排除条件、保留待機条件、非プリエンプティブ条件、ループ待機条件の 4 つです。

デッドロックを避けるには、そのうちの 1 つを破壊してください。

相互排除条件の排除

ロックなど、多くのリソースは 1 つのスレッドによってのみ占有されるため、これを実現することはできません。

リクエストを削除して条件を保持する

この状態を解消する方法は非常に簡単です。つまり、スレッドが必要なすべてのリソースを一度に要求します。

譲れない条件をなくす

あるリソースを占有しているスレッドがさらに他のリソースを申請するとき、申請ができない場合には、占有しているリソースを積極的に解放して、非譲渡性の状態を破壊することができます。

ループ待ち状態の解消

リソースを順番に申請することで防ぐことができます。いわゆるシーケンシャル申請とは、リソースが直線的な順序であることを意味します。申請するときに、最初にシリアル番号の小さいリソースを申請し、次にシリアル番号の大きいリソースを申請できます。このようにすると、線形化後のループは発生しません。 。

14. ライブロックとハンガーロックを理解していますか?

ハンガーロック:

飢餓ロック。この飢餓はリソース飢餓を指します。飢餓のために人間が成長できないのと同じように、スレッドは必要なリソースを待つことができないため、先に進むことができません。

ライブロック:

ライブロック状態では、ライブロック スレッド グループ内のスレッドの状態を変更できますが、ライブロック グループ全体のスレッドを進めることはできません。

ライブロックは、非常に狭い橋を渡る 2 人の人にたとえられます。相手を先に通過させるために、両方の人が側に道を譲りますが、2 人は常に同じ側に道を譲ります。こうして二人の状態は変化していくのに、前に進むことができない。

3. メモリ管理

1. 仮想メモリとは何ですか?

実際の物理メモリは主にメイン メモリですが、物理的なメイン メモリのスペースは限られているため、一般的な最新のオペレーティング システムはメモリ ブロックの一部をディスク上に配置し、必要に応じてメイン メモリにロードする方法を見つけます。使用されていますが、ユーザープログラムでは実際の物理メモリを意識する必要がないのはなぜでしょうか。仮想メモリの仕組みによるものです。

簡単に言えば、仮想メモリは、さまざまなプロセスの仮想アドレスとさまざまなメモリの物理アドレスをマッピングするためにオペレーティング システムによって提供されるメカニズムです。

各プロセスには独自の独立したアドレス空間があり、オペレーティング システムによって実際の物理メモリにマップされます。

したがって、ここではアドレスの 2 つの概念が導入されています。

プログラムが使用するメモリアドレスを仮想メモリアドレス(Virtual Memory Address)といいます。

実際にハードウェアに格納されている空間アドレスを物理メモリアドレス(Physical Memory Address)といいます。
ここに画像の説明を挿入

2. メモリのセグメント化とは何ですか?

プログラムは、コードセグメント、データセグメント、スタックセグメント、ヒープセグメントなどのいくつかの論理セグメントで構成されます。セグメントが異なれば属性も異なるため、これらのセグメントはセグメンテーションの形式で分割されます。

セグメンテーション メカニズムにおける仮想アドレスは、セグメント番号とセグメント内のオフセットの 2 つの部分で構成されます。

仮想アドレスと物理アドレスはセグメントテーブルを通じてマッピングされ、セグメントテーブルには主にセグメント番号とセグメントの境界が含まれます。
ここに画像の説明を挿入
マッピングを見てみましょう。仮想アドレス: セグメント 3、セグメント オフセット 500 ----> セグメント ベース アドレス 7000+ セグメント オフセット 500 ----> 物理アドレス: 7600+。
ここに画像の説明を挿入

3. メモリページングとは何ですか?

ページングとは、仮想メモリ空​​間と物理メモリ空間全体を固定サイズのセグメントに分割することです。このような連続した固定サイズのメモリ空間をページと呼びます。Linux では、各ページのサイズは 4KB です。

ページング システムのメモリ データにアクセスするには、2 つのメモリ アクセスが必要です。1 つはメモリからページ テーブルにアクセスし、指定された物理ページ番号を見つけ、ページ内のオフセットを追加して実際の物理アドレスを取得することです。2 つ目は、最初の時間に基づく実際の物理アドレス 物理アドレスはメモリにアクセスしてデータをフェッチします。
ここに画像の説明を挿入

4. マルチレベルページテーブルをご存知ですか?

オペレーティング システムには多数のプロセスが存在する可能性があり、単純なページングのみを使用すると、ページ テーブルが非常に大きくなる可能性があります。

したがって、マルチレベルページテーブルのソリューションが導入されます。

いわゆるマルチレベル ページ テーブルは、元の単一レベルのページ テーブルを再度ページに分割します。ここでは、局所性の原理が使用されます。トップレベルのページ テーブルを除いて、他のレベルのページ テーブルは、次のときに作成できます。次に、メモリ いざというときにディスクに交換することもできます。
ここに画像の説明を挿入

5. ブロックテーブルとは何ですか?

局所性の原理も使用されます。つまり、一定期間内でプログラム全体の実行がプログラムの特定の部分に限定されます。同様に、実行によってアクセスされる記憶空間も特定のメモリ領域に制限されます。

この機能を利用して、最も頻繁にアクセスされるページ テーブル アイテムは、より高速なアクセス速度でハードウェアに保存されるため、コンピューター科学者は、最も頻繁にアクセスされるページ テーブル エントリを保存する特別なページを CPU チップに追加しました。キャッシュは TLB (Translation Lookaside Buffer) で、通常はページ テーブル キャッシュ、フォワーディング バイパス キャッシュ、高速テーブルなどと呼ばれます。
ここに画像の説明を挿入

6. ページングとセグメンテーションの違いは何ですか?

セグメントは、ユーザーのニーズに応じて分割される情報の論理単位であり、セグメントはユーザーに表示されます。ページは、情報の物理単位であり、メイン メモリの管理の便宜のために分割され、透過的です。ユーザーに。
セグメントのサイズは固定されておらず、それが完了する機能によって決まります。ページのサイズは固定されており、システムによって決まります。セグメントはユーザーに 2 次元のアドレス空間を提供し、ページはユーザーに 1 次元のアドレス空間を提供します
。 -次元アドレス空間
セグメントは、簡単に保存できる情報の論理単位です。情報の保護と共有、ページの保護と共有には制限があります。

7. スワップスペースとは何ですか?

オペレーティング システムは物理メモリ (物理 RAM) を小さなメモリ片に分割し、各メモリ片はページと呼ばれます。メモリ リソースが不十分な場合、Linux はメモリ領域を解放するために特定のページの内容をディスク上の領域に転送します。ディスク上のそのスペースはスワップスペースと呼ばれ、このプロセスはスワッピングと呼ばれます。物理メモリとスワップ領域の合計容量が、仮想メモリの利用可能な容量となります。

使用:

物理メモリが不十分な場合、使用頻度の低い一部のページがシステムにスワップアウトされることがあります。
プログラムの開始時に多くのメモリ ページが初期化に使用されますが、その後は不要になり、スワップアウトできます。

8. ページ置換アルゴリズムとは何ですか?

ページング システムでは、仮想ページはメイン メモリまたはディスクに存在する可能性があります。CPU は、仮想アドレスに対応する物理ページがメイン メモリにないことを検出すると、ページ フォールト割り込みを生成し、ページ フォールト割り込みを生成します。ディスクからのページがメイン メモリに転送されます。

メモリに空きがない場合は、メイン メモリからページを選択して置き換える必要があります。

一般的なページ置換アルゴリズム:
ここに画像の説明を挿入

  • 最適ページ置換アルゴリズム (OPT)
    最適ページ置換アルゴリズムは理想的なアルゴリズムであり、基本的な考え方は、今後長期間アクセスされないページを置換することです。

したがって、このアルゴリズムの実装では、メモリ内の各論理ページの次回アクセス時間を計算し、それらを比較して、将来最も長時間アクセスされないページを選択する必要があります。

しかし、このアルゴリズムは実現できません。ページ フォールトが発生すると、オペレーティング システムは次に各ページがいつアクセスされるかを知ることができないからです。

  • 先入れ先出し置換アルゴリズム (FIFO)
    次のアクセスまでのページの待ち時間を予測できないため、メモリ滞留時間が長いページを置換することを選択できます。これは「先入れ先出し」です。 「置換」アルゴリズムのアイデア。

FIFO の実装メカニズムは、リンク リストを使用してエントリ時間に従ってメモリ内のすべてのページをリンクし、そのたびにリンク リストの先頭のページを置き換え、新しく追加されたページが最後にハングします。リンクされたリストの。
ここに画像の説明を挿入

  • 最も長く使用されていない置換アルゴリズム (LRU) 最も
    長く使用されていない (LRU) 置換アルゴリズムの基本的な考え方は、ページが欠落している場合、最も長い間アクセスされていないページを置換のために選択するというものです。たとえば、このアルゴリズムは、長期間使用されていないページは将来的に長期間使用されない可能性が高いと想定しています。

    このアルゴリズムは最適置換アルゴリズムと似ており、最適置換アルゴリズムは「将来の」使用状況に基づいて削除するページを推測するのに対し、LRU は過去の使用状況に基づいて削除するページを推測します。

    LRU は理論的には可能ですが、コストが高くなります。LRU を完全に実装するには、すべてのページのリンクされたリストをメモリ内に保持する必要があります。その際、最近使用されたページが先頭に、最も最近使用されていないページがリストの最後にあります。
    ここに画像の説明を挿入
    問題は、メモリにアクセスするたびにリンク リスト全体を更新する必要があることです。リンクされたリストからページを見つけて削除し、先頭に移動するのは非常に時間がかかる操作です。

したがって、LRU は良さそうに見えますが、オーバーヘッドが比較的高いため、実際のアプリケーションではほとんど使用されません。

  • 時計ページ置換アルゴリズム
    このアルゴリズムの考え方は、時計の文字盤に似たリングにリンクされたリストにすべてのページを格納し、ポインターが最も古いページを指すことです。
    ここに画像の説明を挿入
    ページフォールトが発生すると、アルゴリズムはまずポインタが指すページをチェックします。

アクセス ビットが 0 の場合、そのページは削除され、新しいページがこの位置に挿入され、ポインタが 1 位置だけ前に移動します。

アクセス ビットが 1 の場合は、アクセス ビットをクリアしてポインタを 1 つ進め、アクセス ビットが 0 のページが見つかるまでこのプロセスを繰り返します。

  • 最も使用頻度の低い置換アルゴリズム
    最も使用頻度の低いアルゴリズム (LFU) では、改ページが発生したときに、アクセス数が最も少ないページを選択して置換します。
    これはページごとに「アクセスカウンタ」を設定することで実現されており、ページにアクセスされるたびにそのページのアクセスカウンタが1ずつインクリメントされます。ページフォルトが発生すると、カウンタ値が最も小さいページが削除されます。

4. 書類

1. ハード リンクとソフト リンクの違いは何ですか?

ハード リンクでは、ディレクトリ内にエントリを作成し、ファイル名と i ノード番号を記録します。この i ノードはソース ファイルの i ノードです。エントリを削除しても、参照数がゼロでない限り、ファイルはまだ存在します。ただし、ハード リンクには制限があり、ファイル システムをまたがることはできず、ディレクトリをリンクすることもできません。
ここに画像の説明を挿入

  • ソフト リンクはファイルの再作成と同等です。このファイルには独立した i ノードがありますが、このファイルの内容は別のファイルのパスであるため、ソフト リンクにアクセスすると、実際には別のファイルにアクセスすることと同じになります。そのため、ソフト リンクは交差する可能性があります。ファイル システム。ターゲット ファイルが削除されても、リンクされたファイルはまだ存在しますが、指定されたファイルを開くことはできません。
    ここに画像の説明を挿入

五、私

1. ゼロコピーを理解していますか?

従来の I/O を使用してファイル転送が必要な場合、データの読み取りと書き込みはユーザー空間からカーネル空間への往復に割り当てられ、カーネル空間のデータはオペレーティング システムの I/O インターフェイスを通じてディスクから読み書きされます。この期間中、ユーザー モードとカーネル モードの間で複数のコンテキスト スイッチが発生し、複数のデータ コピーが発生しました。
ここに画像の説明を挿入
I/O パフォーマンスを向上させるには、ユーザー モードとカーネル モード間のコンテキスト スイッチとメモリ コピーの数を減らす必要があります。

これには当社のゼロコピー テクノロジーが使用されており、ゼロコピー テクノロジーには主に 2 つの実装があります。

  • mmap + write
    mmap() システム コール関数は、カーネル バッファ内のデータをユーザー空間に直接「マッピング」するため、オペレーティング システムのカーネルとユーザー空間はデータ コピー操作を実行する必要がありません。
    ここに画像の説明を挿入
  • Linux カーネル バージョン 2.1 では、 sendfile は
    ファイルを送信するための特別なシステム コール関数 sendfile() を提供します。

まず、前の 2 つのシステム コール、read() と write() を置き換えることができるため、1 つのシステム コールが削減され、2 つのコンテキスト スイッチのオーバーヘッドも削減されます。

第 2 に、このシステム コールは、ユーザー状態にコピーするのではなく、カーネル バッファ内のデータをソケット バッファに直接コピーできるため、コンテキスト スイッチは 2 つとデータ コピーは 3 つだけです。
ここに画像の説明を挿入
Kafka や RocketMQ などの多くのオープンソース プロジェクトは、IO 効率を向上させるためにゼロコピー テクノロジを採用しています。

2. ブロッキングと非ブロッキング **I/O**、同期 I/O と非同期 I/O について話しますか?

  • ブロッキング I/O
    まずブロッキング I/O について見てみましょう. ユーザー プログラムが read を実行すると、スレッドはカーネル データの準備ができるまでブロックされ、カーネル データの準備が完了すると、カーネル バッファからアプリケーション バッファにデータがコピーされます。コピープロセスが完了すると、読み取りが返されます。

注意,ブロックされるのは、カーネル データの準備と、カーネル モードからユーザー モードへのデータ コピーの 2 つのプロセスです。
ここに画像の説明を挿入

  • ノンブロッキング I/O
    ノンブロッキング読み取りリクエストは、データの準備ができていない場合はすぐに返され、実行を続行できます。このとき、アプリケーション プログラムはデータの準備ができるまでカーネルをポーリングし続け、カーネルはデータを次の場所にコピーします。アプリケーション バッファ、読み取り呼び出しで結果を取得できます。
    ここに画像の説明を挿入
  • ノンブロッキング I/O 多重化に基づく
    上記のノンブロッキング I/O には問題があります。何が問題なのでしょうか? アプリケーションは常にポーリングする必要があり、このプロセスは他のことを行うことができないため、I/O 多重化テクノロジが導入されています。

カーネル データの準備ができると、アクションを実行するためのイベントがアプリケーションに通知されます。
ここに画像の説明を挿入注: ブロッキング I/O、ノンブロッキング I/O、ノンブロッキング I/O 多重化のいずれであっても、それらはすべて同期呼び出しです。
読み取りで呼び出された場合、カーネルはカーネル空間からアプリケーション空間にデータをコピーするため、プロセスは待機する必要があり、つまりプロセスが同期的になるため、カーネルによって実装されるコピー効率が高くない場合、読み取り呼び出し ユーザーは同期プロセス中に長時間待つことになります。

  • 非同期 I/O
    本当の非同期 I/O とは、カーネル データの準備とカーネル モードからユーザー モードへのデータ コピーの 2 つのプロセスを待つ必要がないことを意味します。

aio_read を開始した後、すぐに戻り、カーネルはカーネル空間からアプリケーション空間にデータを自動的にコピーします。このコピー プロセスも非同期であり、カーネルが自動的に完了します。これは、前の同期操作とは異なります。アプリケーションは、コピー アクションを積極的に開始する必要はありません。
ここに画像の説明を挿入
いくつかの I/O モデルを理解するために例を取り上げます

3 番目の子供は、多くの UP 所有者をフォローしており、その中には年老いた鳩も含まれており、更新の時期が来ました。

I/O をブロックするということは、3 番目の子は他に何もせず、ただ待って UP の更新を見つめることを意味します。

ノンブロッキング I/O とは、3 番目の子が UP が更新されていないことに気づき、お茶か何かを飲みに行き、しばらくしてから見に来て、UP が更新されるまで待つことを意味します。

たとえば、ノンブロッキング I/O 多重化に基づいて、3 番目の子は UP が更新されていないことに気づき、他のことを実行します。しばらくすると、ステーション B がメッセージをプッシュします。3 番目の子は、UP が更新されていないことを確認します。メッセージが多かったので、ニュースに行き、待機中のUPが更新されているかどうかを確認します。

非同期 I/O とは、3 番目の子が UP を更新するように言い、UP が急いでビデオを作成し、そのビデオを 3 番目の子供に直接提示するというプロセスを意味します。このプロセスを待つ必要はありません。

3. I/O多重化について詳しく教えてください。

まず I/O 多重化とは何なのかを理解しましょう。

従来の I/O モデルでは、サーバーが複数のクライアントをサポートする必要がある場合、クライアントごとにプロセス/スレッドを割り当てる必要がある場合があります。

より重いプロセス モデルに基づいているか、より軽いスレッド モデルに基づいているかに関係なく、接続が多すぎると、オペレーティング システムはそれを処理できません。

そこで導入されたのが I/O 多重化テクノロジーです。

簡単に言えば、1 つのプロセス/スレッドが複数の Socket を維持します。この多重化は、複数の接続が 1 つのプロセス/スレッドを多重化することを意味します。

ここに画像の説明を挿入

  • 選択する

select が多重化を実装する方法は次のとおりです。

接続されているすべての Sockets をファイル記述子セット fd_set に入れ、select 関数を呼び出して fd_set セットをカーネルにコピーし、カーネルにネットワーク イベントがあるかどうかをチェックさせます。チェック方法は非常に大まかです。fd_set を走査することで、イベントが検出され、ソケットを読み取り可能または書き込み可能としてマークし、fd_set 全体をユーザー モードにコピーして戻します。その後、ユーザー モードを再度トラバースする必要があります。メソッドは読み取り可能または書き込み可能なソケットを見つけて、それを処理します。

select はファイル記述子のセットを表すために固定長の BitsMap を使用します, サポートされるファイル記述子の数は制限されています. Linux システムでは, カーネルの FD_SETSIZE によって制限されます. デフォルトの最大値は 1024 であり, サポートされるファイル記述子の数は 1024 のみです0~1023のファイル記述子を監視します。

選択メカニズムの欠点:

(1) select を呼び出すたびに、fd_set セットをユーザー状態からカーネル状態にコピーする必要がありますが、fd_set セットが大きい場合、オーバーヘッドも非常に高くなります。数百万の接続があるアクティブな接続はほんのわずかです。

(2) select が呼び出されるたびに、カーネルによって渡されたすべての fd_set を走査する必要があり、fd_set コレクションが大きい場合、オーバーヘッドも非常に高くなります。

(3) データのコピーによるパフォーマンスの低下を軽減するために、カーネルは監視対象の fd_set セットのサイズを制限しており、通常は 1024 です。変更したい場合は面倒で、コンパイルが必要になる場合があります。カーネル。

(4) 選択する各呼び出しの前に、設定された監視コレクションを走査し、作業を繰り返す必要があります。

  • 世論調査

ポーリングは、関係するファイル記述子の保存に BitsMap を使用しなくなりました。代わりに、リンク リストの形式で編成された動的配列を使用します。これにより、select のファイル記述子の数の制限が突破され、もちろんシステム ファイルの影響を受けます。記述子の制限。

ただし、poll と select の間に本質的な違いはあまりありません。どちらも、プロセスが関係するソケット コレクションを格納するために線形構造を使用します。そのため、両方ともファイル記述子のコレクションを走査して、読み取り可能または書き込み可能なソケットを見つける必要があります。複雑度は O( n) であり、ユーザー モードとカーネル モードの間でファイル ディスクリプタ セットをコピーする必要があるため、同時実行数が増加するにつれてパフォーマンスの損失は指数関数的に増加します。

epoll は、2 つの側面を通じて選択/ポーリングの問題をうまく解決します。

まず、epoll はカーネル内の赤黒ツリーを使用して、プロセス内で検出されるすべてのファイル記述子を追跡し、epoll_ctl() 関数を通じて監視対象のソケットをカーネル内の赤黒ツリーに追加します。 -black Tree は高レベルの効率的なデータ構造であり、追加、削除、チェックの一般的な時間計算量は O(logn) です。この black mangrove を操作することで、各操作でソケット コレクション全体を渡す必要はありませんselect/poll のように、検出されるソケットを渡すと、カーネルお​​よびユーザー空間での大量のデータのコピーとメモリ割り当てが削減されます。

第 2 に、epoll はイベント駆動型のメカニズムを使用します。カーネルは、準備完了イベントを記録するためのリンク リストを維持します。特定のソケットでイベントが発生すると、カーネルはコールバック関数を通じてそのイベントを準備完了イベント リストに追加します。ユーザーが呼び出したときに、 epoll_wait() 関数を使用すると、イベントが発生したファイル記述子の数のみが返され、select/poll のようにソケット コレクション全体をポーリングおよびスキャンする必要がないため、検出効率が大幅に向上します。
ここに画像の説明を挿入
epoll 方式がより多くのソケットを監視しても、効率は大きく低下せず、同時に監視できるソケットの数も非常に多く、上限は、によって定義されたプロセスによってオープンされる最大ファイル記述です。システムのシンボル数。したがって、epoll は C10K 問題を解決するための優れたツールとして知られています。

整理するのは簡単ではありませんが、親指を立てるのは良いことです~~~~

おすすめ

転載: blog.csdn.net/zch981964/article/details/130697825