1 つの記事でオペレーティング システムについて説明します


記事の文字数は約19,000文字、読了時間は約65分、ブックマークしてゆっくり読むのがおすすめ!! !

1. プロセスとスレッドの管理

  1. プロセスとスレッドの基本

    プロセス: プロセスは、システムによるリソース割り当てとスケジューリングの独立した単位であり、システム内での同時実行の単位です。

    スレッド: スレッドは、プロセスの実体であり、CPU スケジューリングおよびディスパッチの基本単位です. プロセスよりも小さく、独立して実行できる基本単位です. 軽量プロセスまたは軽量プロセスと呼ばれることもあります.

    1. プロセス

      実行中のプログラムを「プロセス」と呼びます。

      プロセスの活動中、少なくとも 3 つの基本的な状態、つまり、実行中状態、準備完了状態、およびブロック状態があります。

      • 実行状態 ( Running ): プロセスは現時点で CPU を占有しています。
      • 準備完了状態 ( Ready ): 実行可能、他のプロセスが実行中のため一時的に実行を停止。
      • ブロック状態 ( Blocked ): プロセスはイベントが発生するのを待っており (入出力操作の完了を待っているなど)、一時的に実行を停止しています. この時点では、CPU 制御が与えられていても実行できません。

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

      • 作成状態 ( new ): プロセスが作成されているときの状態。
      • 終了状態 ( Exit ): プロセスがシステムから消えるときの状態。

      保留状態には、次の 2 つのタイプがあります。

      • ブロック保留状態: プロセスは外部メモリ (ハードディスク) にあり、イベントの発生を待機しています。
      • サスペンド準備完了状態: プロセスは外部メモリ (ハードディスク) にありますが、メモリに入るとすぐに実行されます。

      PCB プロセス制御ブロックは、プロセスの存在を一意に識別するものです

      PCB には具体的にどのような情報が含まれていますか?

      プロセス記述情報:

      • プロセス識別子: 各プロセスを識別します。各プロセスには一意の識別子があります。
      • ユーザー識別子:プロセスが属するユーザーであり、ユーザー識別子は主に共有および保護サービス用です。

      プロセス制御および管理情報:

      • 新規、準備完了、実行中、待機中、ブロック中など、プロセスの現在のステータス。
      • プロセスの優先度: CPU をプリエンプトするときのプロセスの優先度。

      リソース割り当てのチェックリスト:

      • メモリ アドレス空間または仮想アドレス空間に関する情報、開いているファイルのリスト、および使用されている I/O デバイスの情報。

      CPU 関連情報:

      • CPU 内の各レジスタの値は、プロセスが切り替わったときに、CPU ステータス情報が対応する PCB に保存されるため、プロセスが再実行されたときに、ブレークポイントから実行を継続できます。
    2. スレッドは、プロセス内の実行の流れです。

      同じプロセス内の複数のスレッドは、コード セグメント、データ セグメント、開いているファイルなどのリソースを共有できますが、各スレッドには独立したレジスタとスタックの独自のセットがあるため、スレッドの制御フローは比較的独立しています。

      スレッドの実装

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

      • ユーザー スレッド (*User Thread*) : カーネルによって管理されるスレッドではなく、ユーザー空間に実装されるスレッドは、ユーザー モード スレッド ライブラリによって管理されます。
      • カーネル スレッド (*Kernel Thread*) : カーネルに実装されているスレッドは、カーネルによって管理されるスレッドです。
      • Lightweight Process (*LightWeight Process*) : カーネル内のユーザー スレッドをサポートします。

      最初の関係は多対1 の関係です。つまり、複数のユーザー スレッドが同じカーネル スレッドに対応します。

      2 つ目は1 対1 の関係です。つまり、1 つのユーザー スレッドが 1 つのカーネル スレッドに対応します。

      3 つ目は多対多の関係です。つまり、複数のユーザー スレッドが複数のカーネル スレッドに対応します。

      ユーザー スレッドの全体的なスレッド管理とスケジューリング、オペレーティング システムは直接関与しませんが、スレッド管理は、スレッドの作成、終了、同期、およびスケジューリングを含むユーザー レベルのスレッド ライブラリ関数によって完了します。

      スレッドの利点:

      • 複数のスレッドが同時にプロセスに存在できます。
      • 各スレッドは同時に実行できます。
      • アドレス空間やファイルなどのリソースは、スレッド間で共有できます。

      スレッドの欠点:

      • プロセス内のスレッドがクラッシュすると、それが属するプロセスのすべてのスレッドがクラッシュします (これは C/C++ 言語の場合であり、Java 言語のスレッド クラッシュによってプロセスがクラッシュすることはありません)。

      カーネルスレッドはオペレーティングシステムによって管理され、スレッドに対応するTCBは当然オペレーティングシステムに配置されるため、スレッドの作成、終了、および管理はすべてオペレーティングシステムによって処理されます。

  2. プロセス/スレッドのコンテキスト切り替え

    1. プロセス

      あるプロセスから別のプロセスへの切り替えは、プロセス コンテキスト スイッチと呼ばれます

      プロセス コンテキスト スイッチとは正確には何ですか?

      プロセスはカーネルによって管理およびスケジュールされるため、プロセスの切り替えはカーネル状態でのみ発生します。

      したがって、プロセスのコンテキスト切り替えには、仮想メモリ、スタック、グローバル変数などのユーザー空間リソースだけでなく、カーネル スタックやレジスタなどのカーネル空間リソースも含まれます。

      通常、交換された情報はプロセスの PCB に保存されますが、別のプロセスが実行される場合は、このプロセスの PCB からコンテキストを取り出して CPU に復元する必要があります。 .

      プロセス コンテキスト スイッチが発生するシナリオは何ですか?

      • すべてのプロセスを公平にスケジュールできるようにするために、CPU 時間はタイム スライスに分割され、これらのタイム スライスが各プロセスに順番に割り当てられます。このようにして、プロセスのタイム スライスが使い果たされると、プロセスは実行中状態から準備完了状態に変わり、システムは実行する別のプロセスを準備完了キューから選択します。
      • システム リソースが不足している場合 (メモリ不足など)、リソースが満たされるまでプロセスを実行できません. この時点で、プロセスも中断され、システムは他のプロセスの実行をスケジュールします;
      • プロセスがスリープ機能 sleep によってアクティブに一時停止すると、プロセスは自然に再スケジュールされます。
      • 優先度の高いプロセスが実行されている場合、優先度の高いプロセスを確実に実行するために、現在のプロセスは中断され、優先度の高いプロセスによって実行されます。
      • ハードウェア割り込みが発生すると、CPU 上のプロセスは割り込みによって中断され、カーネルで割り込みサービス ルーチンが実行されます。
      1. スレッド コンテキストの切り替えとは

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

        1. 2 つのスレッドが同じプロセスに属していない場合、切り替えプロセスはプロセス コンテキストの切り替えと同じです。
        2. 2 つのスレッドが同じプロセスに属している場合、仮想メモリが共有されているため、切り替え時に仮想メモリのリソースは変更されず、スレッドのプライベート データ、レジスタ、およびその他の非共有データのみを切り替える必要があります

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

  3. プロセス/スレッド間の通信

    プロセス間通信 (IPC、InterProcess Communication) は、異なるプロセス間での情報の普及または交換を指します。通常、IPC メソッドには、パイプ (名前のないパイプと名前付きのパイプを含む)、メッセージ キュー、セマフォ、共有ストレージ、ソケット、ストリームなどが含まれます。その中で、Socket と Streams は、異なるホストで 2 つのプロセス IPC をサポートします。

    パイプライン

    1. 固定の読み取りポートと書き込みポートを備えた半二重です。
    2. 親プロセスと子プロセスまたは兄弟プロセス間のプロセス通信にのみ使用できます。
    3. これは特殊なファイルと見なすことができ、読み取りや書き込みなどの通常の機能も使用できます。ただし、通常のファイルではなく、他のファイル システムに属さず、メモリ内にのみ存在します。

    名前付きパイプ

    1. FIFO は、名前のないパイプとは異なり、無関係なプロセス間でデータを交換できます。
    2. FIFO にはパス名が関連付けられており、特別なデバイス ファイルとしてファイル システムに存在します。

    メッセージ待ち行列

    1. メッセージ キューは、カーネルに格納されているメッセージのリンク リストです。メッセージ キューは識別子 ID によって識別されます。
    2. メッセージ キューはレコード指向であり、その中のメッセージには特定の形式と特定の優先度があります。
    3. メッセージ キューは、送信プロセスと受信プロセスから独立しています。プロセスが終了しても、メッセージ キューとその内容は削除されません。
    4. メッセージ キューはメッセージのランダム クエリを実現でき、メッセージは先入れ先出しの順序で読み取る必要はなく、メッセージの種類によって読み取ることもできます。

    信号量

    1. セマフォはカウンターです。プロセス間の通信データを保存するためではなく、プロセス間の相互排除と同期を実現するために使用されます。
    2. セマフォはプロセス間の同期に使用されます.プロセス間でデータを転送するには、共有メモリと組み合わせる必要があります。
    3. セマフォはオペレーティング システムの PV 操作に基づいており、セマフォ上のプログラムの操作はアトミック操作です。
    4. セマフォに対する各 PV 操作は、セマフォ値に 1 を加算または減算することに限定されませんが、任意の正の整数を加算または減算することもできます。
    5. セマフォ グループのサポート。

    共有メモリ

    1. 共有メモリとは、2 つ以上のプロセスが特定のストレージ領域を共有することを意味します。
    2. 共有メモリは、プロセスがメモリに直接アクセスするため、最も高速な IPC のタイプです。

    Socket通信

    上記の通信機構はすべて同一ホスト上で動作しますが、異なるホストのプロセスと通信したい場合はソケット通信が必要です。ソケットは、実際には異なるホストのプロセス間通信だけでなく、ローカル ホストのプロセス間通信にも使用されます. 作成されるソケットの種類に応じて、3 つの一般的な通信方法に分けることができます.1 つは TCP プロトコルに基づいています. 、もう1つはUDPプロトコルに基づく通信方式で、もう1つはローカルなプロセス間通信方式です。

    以上がプロセス間通信の主な仕組みです。スレッド通信の方法はどうですか?

    同一プロセス配下のスレッドはプロセスの資源を共有する. 共有変数であれば, グローバル変数などのスレッド間通信が可能. したがって, スレッド間通信に注目するのは通信方法ではなく,共有リソースのマルチスレッド競合. 問題, セマフォはスレッド間の相互排除と同期も達成できます:

    • 相互排除により、常に 1 つのスレッドのみが共有リソースにアクセスすることが保証されます。
    • 同期の方法により、スレッド A がスレッド B の前に実行されることが保証されます。
  4. スレッドとプロセスがクラッシュするとどうなるか

    一般に、メモリへの不正アクセスによってスレッドがクラッシュした場合、プロセスは必ずクラッシュします.なぜシステムがプロセスをクラッシュさせるのでしょうか.これは主に、プロセス内で各スレッドのアドレス空間が共有されているためです.共有されているため. その後、特定のスレッドによるアドレスへの不正なアクセスは、メモリの不確実性につながり、他のスレッドに影響を与える可能性があります.この操作は危険です.プロセスクラッシュ

    クラッシュメカニズム

    1. CPU は通常のプロセス命令を実行します
    2. kill システム コールを呼び出して、プロセスにシグナルを送信します。
    3. プロセスがオペレーティング システムからシグナルを受信すると、CPU は現在のプログラムを中断し、制御をオペレーティング システムに移します。
    4. kill システム コールを呼び出してプロセスにシグナルを送信します (シグナルが 11、つまり SIGSEGV であると仮定すると、このエラーは通常、メモリへの不正なアクセスに対して報告されます)。
    5. オペレーティングシステムは状況に応じて対応するシグナルハンドラ(関数)を実行し、通常はシグナルハンドラのロジックが実行された後、プロセスは終了します。

    上記の 5 番目のステップに注意してください。プロセスが独自のシグナル処理関数を登録しない場合、オペレーティング システムはデフォルトのシグナル処理プログラムを実行します (通常、プロセスは最後に終了します)。独自のシグナル処理関数, このようにして, プロセスは死ぬ機会を与えられます. kill シグナルを受け取った後, exit() を呼び出して終了できます.プロセス。

  5. デーモン、ゾンビ、孤児

    デーモンプロセス

    制御端末が接続されていないバックグラウンドで実行されるプロセスを指します。制御端末とは独立して定期的に特定のタスクを実行します。Linux のほとんどのサーバーは、Web サーバー プロセス http などのデーモン プロセスとして実装されています。

    デーモン プロセスを作成するための重要なポイント:

    (1) プログラムをバックグラウンドで実行させます。方法は fork() を呼び出して子プロセスを生成し、親プロセスを終了させるというものです。

    (2) setsid() を呼び出して、新しいセッションを作成します。制御端末、ログイン セッション、およびプロセス グループは、通常、親プロセスから継承されます。デーモン プロセスは、setsid() を呼び出してプロセスをセッション リーダーにすることにより、それらを取り除き、それらの影響を受けないようにすることができます。setsid() 呼び出しが成功すると、プロセスは新しいセッション リーダーおよびプロセス リーダーになり、元のログイン セッション、プロセス グループ、および制御端末から分離されます。

    (3) プロセスによる制御端末の再オープンを禁止する。上記の手順の後、プロセスはターミナルなしでセッション リーダーになりましたが、ターミナルを開くために再申請できます。これを回避するには、プロセスをセッション リーダーから外すことで実現できます。fork() を使用して新しい子プロセスを再度作成し、fork を呼び出したプロセスが終了するようにします。

    (4) 不要になったファイル記述子を閉じます。子プロセスは、開いているファイル記述子を親プロセスから継承します。クローズされていないと、システム リソースが浪費され、プロセスが配置されているファイル システムをアンマウントできず、予期しないエラーが発生します。最初に最高のファイル記述子値を取得し、次にループ プロシージャを使用して、0 から最高のファイル記述子値までのすべてのファイル記述子を閉じます。

    (5) カレントディレクトリをルートディレクトリに変更します。

    (6) 親プロセスから子プロセスに継承されたファイル作成マスク ワードは、特定のパーミッションを拒否する場合があります。これを防ぐには、unmask(0) を使用してマスク ワードをゼロにします。

    (7) SIGCHLD シグナルを処理します。サーバー プロセスの場合、リクエストが来ると、多くの場合、リクエストを処理するための子プロセスが生成されます。親プロセスが状態を取得するのを子プロセスが待機すると、子プロセスはゾンビ プロセス (ゾンビ) になり、システム リソースを占有します。親プロセスが子プロセスの終了を待機すると、親プロセスの負荷が増加し、サーバー プロセスの同時実行パフォーマンスに影響します。Linux では、SIGCHLD シグナルの動作を SIG_IGN に設定するだけです。このようにして、子プロセスが終了したときにゾンビ プロセスが生成されることはありません。

    孤立したプロセス

    親プロセスが最初に終了し、子プロセスが終了していない場合、子プロセスの親プロセスが init プロセスになります。(注: どのプロセスにも親プロセスが必要です)。

    1 つ以上の子プロセスがまだ実行されているときに親プロセスが終了すると、それらの子プロセスは孤立します。孤立したプロセスは init プロセス (プロセス番号 1) によって採用され、init プロセスはそれらの状態収集作業を完了します。

    ゾンビプロセス

    子プロセスが最初に終了し、親プロセスがまだ終了していない場合、子プロセスは、実際に終了する前に、親プロセスが子プロセスの終了ステータスを取得するまで待機する必要があります。そうしないと、子プロセスは現時点でゾンビ プロセスになります。 .

    ゾンビプロセスをセットアップする目的は、子プロセスの情報を保持して、後で親プロセスが取得できるようにすることです。これらの情報には、少なくともプロセス ID、プロセスの終了ステータス、およびプロセスが使用した CPU 時間が含まれているため、終了した子プロセスの親プロセスが wait または waitpid を呼び出すと、これらの情報を取得できます。プロセスが終了し、そのプロセスにゾンビの子がいる場合、すべてのゾンビの子の親プロセス ID は 1 (init プロセス) にリセットされます。これらの子プロセスを継承する init プロセスは、それらをクリーンアップします (つまり、init プロセスは子プロセスを待機し、ゾンビ状態を取り除きます)。

    ゾンビプロセスを回避する方法

    • カーネルは、子プロセスの終了を気にしないことをシグナル (SIGCHLD、SIG_IGN) で通知され、カーネルによって再利用されます。親プロセスをハングさせたくない場合は、親プロセスにステートメントを追加できます: signal(SIGCHLD, SIG_IGN); は、子プロセスが親プロセスに送信される SIGCHLD シグナルを親プロセスが無視することを意味します。終了します。
    • 親プロセスは、wait/waitpid などの関数を呼び出して、子プロセスが終了するのを待ちます。子プロセスが終了しない場合、親プロセスはブロックされます。waitpid は WNOHANG を渡して、親プロセスをブロックせずにすぐに返すことができます。
    • 親プロセスが非常にビジーな場合は、signal を使用してシグナル処理関数を登録し、シグナル処理関数で wait/waitpid を呼び出して、子プロセスが終了するのを待つことができます。
    • fork を 2 回呼び出す。親プロセスは最初に fork を呼び出して子プロセスを作成し、次に waitpid を呼び出して子プロセスが終了するのを待ちます。その後、子プロセスは孫プロセスを fork して終了します。このように、子プロセスが終了した後、親プロセスはリサイクルを待ちます. 孫プロセスは親プロセスがすでに終了しているため、孫プロセスは孤立プロセスになり、孤立プロセスは init プロセスに引き継がれます.孫のプロセスが終了すると、init はリサイクルを待ちます。

    最初の方法は SIGCHLD シグナルを無視します。これは、並行サーバーが多くの子プロセスをフォークすることが多く、子プロセスが終了した後、サーバー プロセスはリソースのクリーンアップを待機する必要があるため、並行サーバーのパフォーマンスのトリックとしてよく使用されます。このシグナルの処理方法が無視に設定されている場合、カーネルは処理のためにゾンビの子プロセスを init プロセスに転送し、多数のゾンビ プロセスがシステム リソースを占有するのを防ぐことができます。

  6. プロセスとスレッドの比較

    スレッドはスケジューリングの基本単位であり、プロセスはリソース所有権の基本単位です

    スレッドとプロセスの比較は次のとおりです。

    • プロセスはリソース割り当て (メモリ、開いているファイルなどを含む) の単位であり、スレッドは CPU スケジューリングの単位です。
    • プロセスには完全なリソース プラットフォームがありますが、スレッドはレジスタやスタックなどの必須リソースのみを排他的に共有します。
    • スレッドには、準備完了、ブロック、実行という 3 つの基本的な状態もあり、状態間の遷移関係もあります。
    • スレッドは、同時実行の時間とスペースのオーバーヘッドを削減できます。

    スレッドは、プロセスと比較してオーバーヘッドを削減できます。これは、以下に反映されています。

    • プロセスはメモリ管理情報やファイル管理情報などのリソース管理情報も必要とするため、スレッド作成時間はプロセスよりも高速ですが、スレッド作成プロセスはこれらのリソース管理情報に関与せず、それらを共有します。
    • スレッドによって解放されるリソースはプロセスのリソースよりもはるかに少ないため、スレッドの終了時間はプロセスの終了時間よりも高速です。
    • 同じプロセス内のスレッドの切り替えは、スレッドが同じアドレス空間 (仮想メモリ共有) を持っているため、プロセスの切り替えよりも高速です。つまり、同じプロセスのスレッドは同じページ テーブルを持ち、切り替え時にページ テーブルを切り替える必要はありません。 . プロセス間の切り替えでは、切り替え時にページテーブルを切り替える必要があり、ページテーブルの切り替えプロセスは比較的高価です。
    • 同じプロセスのスレッドはメモリとファイル リソースを共有するため、スレッド間のデータ転送はカーネルを経由する必要がなく、スレッド間のデータのやり取りがより効率的になります。

    したがって、時間効率であろうと空間効率であろうと、スレッドはプロセスよりも優れています。

    1. スレッドの起動速度が速く軽量

    2. スレッドのシステム オーバーヘッドが小さい

    3. スレッドの使用が難しく、データの一貫性の問題に対処する必要がある

    4. 同じスレッドがヒープ、グローバル変数、静的変数、ポインター、参照、ファイルなどを共有し、スタックのみを占有します

    1. プロセスはリソース割り当ての最小単位であり、スレッドは CPU スケジューリングの最小単位です。
    2. プロセスを作成またはキャンセルするには、システムはそのプロセスにリソースを割り当てるか再利用する必要があり、オペレーティング システムのオーバーヘッドは、スレッドの作成またはキャンセルのオーバーヘッドよりもはるかに大きくなります。
    3. 異なるプロセスのアドレス空間は互いに独立しており、同じプロセス内のスレッドは同じアドレス空間を共有します。あるプロセスのスレッドは、別のプロセス内では見えません。
    4. プロセスが相互に影響を与えることはなく、スレッドがハングするとプロセス全体がハングする可能性があります。

2. メモリ管理

  1. 物理アドレス、論理アドレス、仮想メモリの概念

    1. 物理アドレス: アドレス変換の最終アドレスです. プロセスが実行時に命令を実行してデータにアクセスするとき, メモリユニットの実アドレスである物理アドレスを介してメインメモリからアクセスする必要があります.
    2. 論理アドレス: コンピュータのユーザーに表示されるアドレスを指します。たとえば、長さが 100 の整数配列を作成すると、オペレーティング システムは論理的に連続したスペースを返します。ポインタは、配列の最初の要素のメモリ アドレスを指します。整数要素のサイズは 4 バイトであるため、2 番目の要素のアドレスは開始アドレスに 4 を加えたものになります。実際、論理アドレスは必ずしも要素が格納されている実際のアドレス、つまり配列要素の物理アドレス (メモリ スティック内の場所) であるとは限りません。これは連続していませんが、オペレーティング システムは論理アドレスをマップします。アドレス マッピングを使用して連続したアドレスに変換する. はい、これは人々の直感的な考え方に沿ったものです。
    3. 仮想メモリ: これは、コンピュータ システムのメモリ管理のテクノロジです。これにより、アプリケーションは連続して使用可能なメモリ (連続した完全なアドレス空間) を持っていると認識しますが、実際には、通常は複数の物理メモリ フラグメントに分割され、一部は一時的に外部ディスク ストレージに格納されます。
  2. 仮想メモリの利点は何ですか

    • まず, 仮想メモリは, プロセスの実行メモリが物理メモリのサイズを超えることがあります. プログラムは局所性の原則に従って実行されるため, CPU はメモリに繰り返しアクセスする明らかな傾向があります.頻繁に使用されない場合は、ハードディスクのスワップ領域などの物理メモリからスワップできます。
    • 第 2 に、各プロセスには独自のページ テーブルがあるため、各プロセスの仮想メモリ空​​間は互いに独立しています。プロセスが他のプロセスのページ テーブルにアクセスする方法はないため、これらのページ テーブルはプライベートであり、複数のプロセス間のアドレス競合の問題が解決されます。
    • 第 3 に、物理アドレスに加えて、ページ テーブルのページ テーブル エントリには、ページの読み取りと書き込みのアクセス許可の制御、ページが存在するかどうかのマークなど、属性をマークするいくつかのビットもあります。オペレーティング システムは、メモリ アクセスに関して優れたセキュリティを提供します。
  3. メモリ管理

    メモリ管理の概念は、オペレーティング システムによるメモリの分割と動的割り当てです。

    メモリ管理機能:

    メモリ空間の割り当てと回復: メイン メモリ空間の割り当てと管理はオペレーティング システムによって完了されるため、プログラマはメモリ割り当ての問題から解放され、プログラミングの効率が向上します。
    アドレス変換: 論理アドレスを対応する物理アドレスに変換します。
    メモリ空間の拡張: 仮想ストレージ テクノロジまたは自動オーバーレイ テクノロジを使用して、メイン メモリを論理的に拡張します。
    ストレージ保護: 各ジョブが互いに干渉することなく、独自のストレージ スペースで実行されるようにします。
    プロセスの作成は、プログラムとデータをメモリにロードすることから始まります。ユーザー ソース プログラムをメモリ内で実行できるプログラムに変換するには、通常、次の手順が必要です。

    コンパイル: コンパイラは、ユーザー ソース コードをいくつかのターゲット モジュールにコンパイルします (高級言語を機械語に変換します)
    。ローディング モジュールはターゲット モジュールによって生成され、リンク後に完全な論理アドレスが形成されます)
    ローディング: ローディング プログラムは、動作のためにローディング モジュールをメモリにロードし、ロード後に物理アドレスを形成します
    。プログラム方法:

    静的リンク: プログラムが実行される前に、ターゲット モジュールとそれらに必要なライブラリ関数が完全な実行可能ファイル (ロードされたモジュール) にリンクされ、その後、逆アセンブルされません。
    ロード時の動的リンク: 各ターゲット モジュールがメモリにロードされると、ロード中にリンク メソッドがリンクされます。
    ランタイム動的リンク: プログラムの実行中にターゲット モジュールが必要になると、リンクされます。その利点は、変更や更新が容易であり、対象モジュールの共有を容易に実現できることです。
    メモリ読み込みモジュールには、メモリを読み込むときに次の 3 つのメソッドがあります。

    再配置: メモリの現在の状況に応じて、ロード モジュールをメモリの適切な場所にロードします. ロード中にターゲット プログラムの命令とデータを変更するプロセスは、再配置と呼ばれます.

    静的再配置: 通常、アドレス変換はロード時に 1 回行われます。ジョブがメモリにロードされるとき、必要なすべてのメモリ領域を割り当てる必要があります.十分なメモリがない場合、ジョブはロードできません. さらに、ジョブがメモリに読み込まれると、実行期間全体にわたってメモリ内で移動したり、メモリ領域に適用したりすることはできません。
    動的再配置: 再配置レジスタのサポートが必要です。プログラムを不連続な記憶領域に割り当てることができ、プログラムの実行前にコードの一部のみをロードして動作させ、プログラムの実行中に必要に応じてメモリを動的に割り当てることができます。
    メモリを割り当てる前に、オペレーティング システムをユーザー プロセスから保護し、ユーザー プロセスを他のユーザー プロセスから保護する必要があります。メモリ保護には、次の 2 つの方法があります。

    CPUに上限レジスタと下限レジスタのペアを設定し、ユーザジョブの上限アドレスと下限アドレスをメインメモリに格納し、CPUがアドレスにアクセスするたびに、2つのレジスタの値と比較して、範囲外かどうかを判断します。
    この保護は、再配置レジスタ (またはベース アドレス レジスタ) と境界アドレス レジスタ (制限長メモリとも呼ばれます) を使用して実現されます。再配置レジスタには物理アドレスの最小値が含まれ、バインド アドレス レジスタには論理アドレスの最大値が含まれます。各論理アドレス値は、境界アドレス レジスタよりも小さくなければなりません。メモリ管理組織は、論理アドレスを境界アドレス レジスタと動的に比較します。アドレスが境界を超えていない場合は、再配置レジスタの値を追加し、それを物理アドレス レジスタにマップします。メモリーユニットに送信します。

  4. 一般的なメモリ割り当て方法

    (1) 静的記憶領域から割り当てられます。メモリはプログラムのコンパイル時に割り当てられ、このメモリはプログラムの実行中ずっと存在します。グローバル変数、静的変数など。

    (2) スタック上に作成されます。関数が実行されると、関数内のローカル変数のストレージ ユニットがスタック上に作成され、関数の実行が終了すると、これらのストレージ ユニットは自動的に解放されます。スタックメモリ割り当て操作はプロセッサの命令セットに組み込まれており、非常に効率的ですが、割り当てられるメモリ容量は限られています。

    (3) ヒープからの割り当て。動的メモリ割り当てとも呼ばれます。プログラムの実行中は、malloc または new を使用して任意の量のメモリを適用します。メモリを解放するためにいつ free または delete を使用するかはプログラマの責任です。動的メモリの寿命は私たちによって決定され、非常に柔軟に使用できますが、最も問題もあります。

    一般的なメモリ割り当てメモリ エラー

    (1) メモリの割り当てに失敗しましたが、使用されました。

    (2) メモリ確保は成功しているが、初期化前に参照されている。

    (3) メモリ割り当ては成功し、初期化されましたが、操作がメモリの境界を越えました。

    (4) メモリを解放するのを忘れて、メモリ リークが発生しました。

    (5) メモリは解放されますが、引き続き使用されます。次の 3 つの一般的な状況があります。

    • プログラム内のオブジェクトの呼び出し関係が複雑すぎて、オブジェクトがメモリを解放したかどうかを判断するのは非常に困難です. この時点で、データ構造を再設計して、オブジェクト管理の混沌とし​​た状況を根本的に解決する必要があります.
    • 関数の return 文の書き方が間違っている 「スタックメモリ」を指す「ポインタ」や「参照」を返さないように注意してください.関数本体の終了時にメモリは自動的に破棄されます.
    • free または delete を使用してメモリを解放した後、ポインタは NULL に設定されません。「ワイルドポインター」につながります。
  5. malloc はどのようにメモリを割り当てますか

    オペレーティング システムから見ると、malloc は brk と mmap の 2 つのシステム コールによって実装されます。

    • Brk は、プロセス データ セグメント (.data) の最上位アドレス ポインターをより高い場所に移動することです. この手順により、実行時にプロセスのヒープ サイズを拡張できます。
    • mmap は、プロセスの仮想アドレス空間で空き仮想メモリの断片を見つけることで、操作可能なヒープ メモリの断片を取得できます。

    通常、割り当てられたメモリが 128k 未満の場合は brk 呼び出しを使用して仮想メモリを取得し、128k を超える場合は mmap を使用して仮想メモリを取得します。

    プロセスは、まずこの 2 つのシステム コールを介してプロセスの仮想メモリを取得または拡張し、対応する仮想アドレスを取得します.これらの仮想アドレスにアクセスすると、カーネルはページ フォールト割り込みを介して対応する物理メモリを割り当てます。完了しました。

  6. 先読み無効化とキャッシュ汚染を回避する方法

    先読みの無効化

    これらのプリロードされたページはアクセスされません。つまり、先読み作業が無駄になり、これが先読み失敗です。

    従来の LRU アルゴリズムでは、次の 2 つの問題を回避できません。

    • 先読みの失敗は、キャッシュ ヒット率の低下につながります。
    • キャッシュ汚染は、キャッシュ ヒット率の低下につながります。

    「先読みエラー」の影響を回避するために、Linux と MySQL は従来の LRU リンク リストに改良を加えました。

    • Linux オペレーティング システムは、アクティブ LRU リスト (アクティブ リスト) と非アクティブ LRU リスト (非アクティブ リスト) の2 つの LRU リストを実装しています。
    • MySQL Innodb ストレージ エンジンは、LRU リンク リストで、若い領域と古い領域の2 つの領域に分割されます。

    キャッシュ汚染

    これらの大量のデータが長時間アクセスされない場合、アクティブな LRU リスト (または若い領域) 全体が汚染されます。

    「キャッシュ汚染」の影響を回避するために、Linux オペレーティング システムと MySQL Innodb ストレージ エンジンは、ホット データへのアップグレードのしきい値をそれぞれ引き上げました。

    • Linux オペレーティング システム: メモリ ページが2 回目にアクセスされると、ページは非アクティブ リストからアクティブ リストにアップグレードされます。

    • MySQL Innodb: メモリ内ページにアクセス

      2回目

      、ページは古い領域から若い領域にすぐにはアップグレードされません。

      旧エリア滞在時間判定:

      • 2 回目のアクセス時間が最初のアクセス時間 (デフォルト値) の 1 秒以内の場合、ページは古い領域から若い領域にアップグレードされません。
      • 2 回目のアクセス時間が最初のアクセス時間から1 秒を超える場合、ページ古い領域から新しい領域にアップグレードされます。

    アクティブ リスト (または若い領域) に入るしきい値を上げることで、キャッシュ汚染の影響を回避することができます。

  7. 物理メモリ管理

    オペレーティング システムの物理メモリ管理には、主にプログラムのロード、スイッチング テクノロジ、連続割り当て管理方法、不連続割り当て管理方法 (ページング、セグメンテーション、セグメント ページング) が含まれます。

    継続的な割り当て管理

    連続メモリ割り当て
    メモリフラグメント
    プログラムにスペースを割り当てるとき、利用できない空きフラグメントスペースが存在する場合があります。
    1. 外部断片化:アロケーションユニット間で利用できないメモリ断片化
    2. 内部断片化:タスクに割り当てられたメモリサイズが、タスクが必要とするメモリサイズよりも大きい場合、余分なメモリ断片化が発生します。

    パーティションの動的割り当て
    連続メモリ割り当て: アプリケーション プログラムをハードディスクからメモリにロードし、メモリの一部をメモリに割り当てます。アプリケーションは、データにアクセスするために実行されます。これは、データ用の連続したメモリ空間です。

    メモリ割り当てアルゴリズム:
    特定の問題に対する適応アルゴリズムを分析します。

    1. 最初の適合:
      定義: メモリ サイズが必要なサイズよりも大きい最初の使用可能な空きブロックを使用します。
      実装方法: アドレスで並べ替えられた空きブロックのリストが必要です。メモリ要件を満たす最初の空きブロックを探します。リサイクルの場合、空きブロックを隣接する空きブロックとマージする問題を考慮する必要があります。
      利点: シンプルで、より大きな空きブロックを簡単に生成でき、アドレス空間の最後に割り当てることができる
      欠点: 外部フラグメントを生成するが、不確実性がある

    2. 最適:
      定義: フリー ブロック全体で割り当て要求を最もよく満たし、メモリの差が最も小さいフリー ブロックを見つけます。
      実装方法: サイズでソートされた空きブロックのリストを用意し、割り当てを最もよく満たすメモリ ブロックを見つける必要があります。リサイクルの場合、空きブロックを隣接する空きブロックとマージする問題を考慮する必要があります。
      利点: 大きなフリー ブロックの分割を回避し、外部フラグメントの生成を最小限に抑え、シンプルにします。
      欠点: 外部フラグメントは非常に薄く、多くの小さなフラグメントがあり、その後の割り当て管理に役立ちません。

    3. ワースト フィット:
      定義: ギャップが最大の空きメモリ ブロックを見つけます。
      実装: サイズでソートされた空きブロックのリストが必要であり、最大のギャップを持つメモリ ブロックを探す必要があります。リサイクルの場合、空きブロックを隣接する空きブロックとマージする問題を考慮する必要があります。
      利点: 小さな外部フラグメントを回避し、割り当て効率が高く、大規模で高速な割り当てに適しています
      欠点: 大きなブロック要求に一定の影響があります

    メモリの断片化を減らす方法

    1. コンパクト: コンパクト デフラグ
      プログラムの実行場所を調整します。
      1.移転のタイミング。プログラムの実行中は実行できませんが、プログラムの待機中はコピーできます。
      2. メモリのコピーは高価です。

    2. スワッピング: Exchange スタイルの最適化では、
      ハード ディスクをバックアップとして使用します。データ(主記憶)を含む待機プログラムをハードディスクに移動します。ハードディスク上のプログラムを実行する必要がある場合、プログラムはメイン メモリにコピーされます。
      1. オーバーヘッドを減らすためにそのプログラムを交換する
      2. 交換のタイミング

    不連続なメモリ割り当て

    連続メモリ割り当てと不連続メモリ割り当て
    連続メモリ割り当ての短所: 1. プログラムに割り当てられた物理メモリが連続的であり、メモリ使用率が低く、外部断片化と内部断片化の問題があります。
    非連続メモリ割り当ての利点: 1. プログラムの物理アドレスが非連続である 2. メモリの使用率と管理が向上する 3. コードとデータの共有が可能になる 4. 動的ロードと動的リンクがサポートされる 非連続メモリ割り当ての欠点:仮想アドレスから物理
    アドレスへのマッピングを確立すると、ソフトウェアのオーバーヘッドが大きすぎるため、ハードウェア サポートを使用できます
    - 「ハードウェア 2 つの管理スキーム: セグメントとページ
    セグメント プログラム
    メモリのセグメント アドレス空間
    は、プログラム (メイン プログラム + サブルーチン + + 変数 (スタック、ヒープ、共有データ セグメント)
    セグメンテーション: 分離と共有の改善、論理アドレス空間の複数の物理アドレス空間への分散、
    論理アドレスの連続性、物理空間へのさまざまな機能のマッピング、これらのセグメントさまざまなサイズ、さまざまな位置

    セグメント化されたアドレッシング機構はハードウェアによって実現されます.
    1次元の論理アドレスは異なるセグメントで構成されています. まず, 論理アドレスは2つのセグメントに分割されます: セグメントアドレッシング (セグメント番号) + セグメントオフセットアドレッシング (addr). で論理メモリを見つけます
    .セグメント番号からセグメント テーブル セグメントの開始アドレス。セグメントの開始アドレスがセグメント サイズの制限を満たしているかどうかを確認します。満たされていない場合はメモリ例外が返され、満たされている場合は論理アドレスとオフセットは物理アドレスです。

    セグメントテーブル:
    1. 論理アドレスのセグメント番号と物理アドレスのセグメント番号のマッピング関係を格納
    2. セグメントサイズと開始アドレスを格納
    セグメントテーブルの確立: アドレッシングの前にオペレーティングシステムが確立されます。

    ページング
    ページング アドレス空間には、
    ページ番号とページ アドレス オフセットが必要です。セグメンテーションと比較して、ページングにはページ フレーム サイズが固定されています。
    物理メモリを固定サイズのフレームに分割し、論理アドレスのページを同じメモリ サイズに分割することができます。サイズは 2 のべき乗です。
    確立方式
    Page frame (Frame): 物理メモリを等サイズのフレームに分割 メモリの物理
    アドレスは (f, o) の 2 組
    物理アドレス = 2^S*f+o
    f はフレーム番号 (F oはフレーム内オフセット (S ビット、フレームあたり 2 S バイト)、

    ページ (Page): 論理アドレス空間は等しいサイズのページに分割されます.
    ページ オフセット サイズ = フレーム オフセット サイズ (ページ フレーム サイズとページ サイズは同じです)
    ページ番号サイズとフレーム番号サイズは一致しない場合があります

    論理アドレスは 2 タプル (p,o)
    論理アドレス = 2^S*p+o
    p: ページ番号 (P ビット、2 P ページ)、o: ページ オフセット (S ビット、ページあたり 2 ページS バイト) )

    ページ アドレス指定メカニズム
    CPU アドレス指定 (論理アドレス)。論理アドレスには 2 つの部分 (p、o) が含まれます。まず、p (ページ番号) がインデックスとして使用され、ページ テーブル ベース アドレス ルックアップ テーブル内の対応するフレーム番号が追加されます。 (pagetable) (物理アドレスの f)、フレーム番号にページ オフセットを加えたものが物理アドレス (f、o) であることを知っています。

    ページ テーブル: ページ番号でインデックス付けされた対応するフレーム番号 (物理アドレス) この目的のために、ページ テーブルのベース アドレスの場所 (ページ番号が開始するアドレス) を知る必要があります。
    ページ テーブルの確立: オペレーティング システムを初期化する場合、ページング メカニズムを有効にする前に確立する必要があります。

    ページングとセグメンテーション:
    ページング: セグメンテーションと比較して、ページング ページ メモリは固定されているため、ページ内のオフセットの範囲が固定されます。セグメンテーションのような一貫性のないページ サイズの問題を考慮する必要はありません。
    論理アドレスと物理アドレス空間
    1. 論理ページの合計サイズが物理フレームの合計サイズと一致せず、一般的な論理アドレス空間が物理アドレス空間よりも大きい。
    2. 論理アドレス空間は連続していますが、物理アドレス空間は不連続です。内部および外部のゴミを減らします。
    ページ テーブル
    ページ テーブルの構造
    ページ テーブルは配列であり、インデックスはページ番号であり、対応する配列項目にはフレーム番号が含まれます。

    ページング メカニズムのパフォーマンスの問題
    1. 時間のオーバーヘッド: メモリ ユニットへのアクセスには 2 回のメモリ アクセスが必要

    ページテーブルは CPU に配置できず、メモリにのみ配置できます.CPU はまずメモリアドレッシングを実行してページテーブルのベースアドレスを見つけ、次にページテーブルアクセスを実行します.2 つのメモリアクセスが実行され、アクセス速度が非常に遅い。

    2 スペース コスト: ページ テーブルが占めるスペース

    1. 64 ビット コンピューター、ページあたり 1 KB、ページ テーブル サイズ? 2^54 ページ テーブル、非常に大きい
    2. 複数のプログラムが複数のページ テーブルを持つ

    解決
    時間: キャッシュ - 高速テーブル、TLB、トランスレーション ルックアサイド バッファ
    TLB:

    共通に使用されるページ番号とフレーム番号のペアを格納する CPU 内のキャッシュ領域は、連想メモリによって実現され、高速アクセス機能を備えています。
    - CPU がアドレッシングを行う場合、まずページ番号を介して TLB を検索し、ページ番号のキーがあるかどうかを確認し、それに応じてフレーム番号を取得し、次に物理アドレスを取得します (物理アドレスへのアクセスを減らします)。 )。TLB ミス、この項目を TLB に更新します (x86CPU このプロセスはハードウェアによって実行され、mps の場合はオペレーティング システムによって実行されます)。
    プログラムを記述する場合は、アクセスしたアドレスをページ番号に記述してください。
    スペースに関して: 間接アクセス (マルチレベル ページ テーブル メカニズム)、タイム フォー スペース
    セカンダリ ページ テーブル:

    論理アドレス (p1, p2, o) の場合、
    CPU は最初にアドレス指定時に p1 を介して第 1 レベルのページ テーブルを検索します. 開始アドレスはオフセット p2 に対して検索され、対応するストレージはフレーム番号です. 時間のオーバーヘッドは増加しますが、第 1 レベルのページ テーブルにページ テーブル エントリがない場合、第 2 レベルのページ テーブル エントリのメモリを占有する必要がないため、スペースを節約できます。
    マルチレベルのページテーブル

    ページ番号をK個に分割し、ページテーブル「ツリー」を設ける

  8. ファストウォッチ

    連想レジスタ (TLB) とも呼ばれる高速テーブルは、アクセス速度がメモリよりもはるかに高速なキャッシュ メモリであり、アドレス変換プロセスを高速化するために現在アクセスされている複数のページ テーブル エントリを格納するために使用されます。これに対応して、メモリ内のページ テーブルは、多くの場合、低速テーブルと呼ばれます。

    アドレス変換プロセス 論理アドレスにアクセスするためのメモリ アクセスの数
    ベースアドレス変換メカニズム ① ページ内のページ番号とオフセットを計算する ② ページ番号の正当性をチェックする ③ ページテーブルをチェックして、ページに格納されているメモリブロック番号を見つける ④ メモリブロック番号とページ内のオフセットに従って物理アドレスを取得する⑤対象メモリユニットへアクセス 2回のフェッチ
    高速テーブルによるアドレス変換メカニズム ①ページ番号とページ内オフセットを計算 ②ページ番号の正当性をチェック ③早見表をチェック。ヒットすればそのページに格納されているメモリブロック番号を知ることができ、そのまま⑤へ、ヒットしなければ④へ ④ ページテーブルを調べて、ページに格納されているメモリブロック番号を探す、ページテーブルエントリを高速テーブルにコピー ⑤ メモリブロック番号とページオフセットから物理アドレスを取得 ⑥ 対象メモリユニットにアクセス 高速テーブル ヒットには 1 回のメモリ アクセスしか必要ありませんが、高速テーブル ミスには 2 回のメモリ アクセスが必要です。
  9. メモリスワップ技術

    スワップ (swap) テクノロジの設計思想: メモリ スペースが不足している場合、システムはメモリ内の一部のプロセスを外部メモリから一時的にスワップし、外部メモリ内の一部のプロセスを実行する準備ができているものにスワップします。メモリ (プロセスはメモリとディスクの間で動的に転送されます。スケジューリング)

    スワップイン: CPU を奪い合う準備が整ったプログラムを補助記憶装置からメイン メモリに移動します。スワップアウト: 待機状態にある (または CPU スケジューリングの原則の下で実行電力が奪われている) プログラムをメモリーから補助記憶装置に移動して、メモリー・スペースを解放します。

    **スワッピングのタイミング:** メモリ スワッピングは通常、多くのプロセスが実行されていてメモリが不足しているときに実行され、一時停止するとシステムの負荷が軽減されます。たとえば、多くのプロセスが実行されているときにページ フォールトが頻繁に発生する場合は、メモリが不足していることを意味し、この時点で一部のプロセスをスワップ アウトできます。ページ フォールト率が大幅に低下した場合は、スワップ アウトを一時停止できます。 .

    キーポイント

    1. スワップにはバッキング ストレージ (通常は高速ディスク) が必要です。これは十分な大きさが必要であり、これらのメモリ イメージに直接アクセスできる必要があります。
    2. CPU を有効に使用するためには、各プロセスの実行時間がスワップ時間よりも長くなる必要があり、スワップ時間に影響を与える主な要因は転送時間であり、これはスワップされたスペース メモリに比例します。
    3. たとえば、プロセスがスワップアウトされている場合は、プロセスのメモリ空間が比例していることを確認してください。
    4. スワップ領域は通常、ディスクのブロック全体として使用され、ファイル システムから独立しているため、非常に高速に使用できます。
    5. スワップは通常、多くのプロセスが実行されていてメモリ容量が不足しているときに開始され、システムの負荷が減少すると一時停止します。
    6. 通常の swap はあまり使用されませんが、swap 戦略の一部のバリアントは、多くのシステム (UNIX システムなど) で引き続き機能します。
  10. ページングとセグメンテーションの違い

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

3. 工程スケジューリングアルゴリズム

  1. 工程スケジューリングアルゴリズムの詳細紹介

    実行するプロセスを選択する機能はオペレーティング システムで行われ、通常はスケジューラ( scheduler ) と呼ばれます。

    スケジューリングのタイミング

    プロセスのライフ サイクルでは、プロセスがある実行状態から別の実行状態に変わると、実際にスケジューリングがトリガーされます。

    たとえば、次の状態変化は、オペレーティング システムのスケジューリングをトリガーします。

    • 準備完了状態から -> 実行中状態: プロセスが作成されると、プロセスは準備完了キューに入り、オペレーティング システムは実行する準備完了キューからプロセスを選択します。
    • 実行中状態から -> ブロッキング状態: プロセスが I/O イベントによってブロックされると、オペレーティング システムは実行する別のプロセスを選択する必要があります。
    • From running state -> end state : プロセスが終了すると、オペレーティング システムは実行する準備完了キューから別のプロセスを選択する必要があります。

    これらの状態が変わると、オペレーティング システムは、新しいプロセスを CPU で実行できるようにするか、または現在のプロセスを CPU から終了させて​​別のプロセスを実行できるようにするかを検討する必要があるためです。

    さらに、ハードウェア クロックが特定の頻度の定期的な割り込みを提供する場合、スケジューリング アルゴリズムは、クロック割り込みの処理方法に応じて 2 つのカテゴリに分けることができます。

    • 非プリエンプティブ スケジューリング アルゴリズムは、プロセスを選択し、ブロックされるまでプロセスを実行するか、プロセスが終了するまで別のプロセスを呼び出さない、つまり、クロックの中断を気にしません。
    • プリエンプティブ スケジューリング アルゴリズムはプロセスを選択し、そのプロセスを一定時間実行させます。プロセスがその時間の最後にまだ実行されている場合、そのプロセスは一時停止され、スケジューラは準備完了キューから別のプロセスを選択します。このプリエンプティブ スケジューリング プロセスでは、タイム スライス メカニズムと呼ばれるスケジューリングのために CPU 制御をスケジューラに戻すために、時間間隔の最後にクロック割り込みが発生する必要があります。

    スケジューリングの原則

    • CPU 使用率: スケジューラは、CPU が常にラッシュ状態であることを確認する必要があります。これにより、CPU 使用率が向上します。
    • システム スループット: スループットは、単位時間あたりに CPU によって完了されるプロセスの数を表します. 長いジョブ プロセスはより長い CPU リソースを占有するため、スループットが低下します. 逆に、短いジョブ プロセスはシステム スループットを増加させます;
    • ターンアラウンド タイム: ターンアラウンド タイムは、実行中のプロセス + ブロッキング時間 + 待機時間の合計です. プロセスのターンアラウンド タイムが小さいほど良い;
    • 待機時間: この待機時間は、ブロック状態の時間ではなく、プロセスが準備完了キューにある時間です. 待機時間が長いほど、ユーザーは不満を感じます.
    • 応答時間: ユーザーが最初に要求をシステムに送信して応答を生成するのにかかる時間. 対話型システムでは、応答時間はスケジューリング アルゴリズムの品質を測定するための主要な基準です.

    スケジューリングアルゴリズム

    スケジューリング アルゴリズムとは、システムのリソース割り当て戦略に従って規定されたリソース割り当てアルゴリズムを指します。一般的に使用されるスケジューリング アルゴリズムには、先着順スケジューリング アルゴリズム、タイム スライス ラウンド ロビン スケジューリング アルゴリズム、短いジョブ優先度スケジューリング アルゴリズム、最短残り時間優先度、高応答率優先度スケジューリング アルゴリズム、優先度スケジューリング アルゴリズムなどがあります。

    • 先着順スケジューリング アルゴリズム

    先着順スケジューリング アルゴリズムは、最も単純なスケジューリング アルゴリズムであり、先入れ先出しまたは厳密なキューイング スキームとしても知られています。各プロセスの準備が整うと、準備完了キューに追加されます。現在実行中のプロセスは実行を停止し、最も長い時間準備完了キューにあったプロセスが選択されて実行されます。このアルゴリズムは、ジョブのスケジューリングとプロセスのスケジューリングの両方に使用できます。先着順は通常のジョブ (プロセス) に適していますが、セグメント化されたジョブ (プロセス) には適していません。

    • タイム スライス ラウンドロビン スケジューリング アルゴリズム

    タイム スライス ラウンド ロビン スケジューリング アルゴリズムは、主に時分割システムに適用されます。このアルゴリズムでは、システムはすべての準備完了プロセスを到着時間順にキューに配置し、プロセス スケジューラは常に準備完了キュー内の最初のプロセスを選択して実行します。 1 つを実行できます。タイム スライス。

    • ショート ジョブ ファースト スケジューリング アルゴリズム

    short-job-first スケジューリング アルゴリズムは、short-job Priority スケジューリング アルゴリズムを指します。これは、バックアップ キューから推定実行時間が最も短い 1 つまたは複数のジョブを選択し、メモリに転送して実行します。短いジョブの優先度スケジューリング アルゴリズムは非先取り戦略であり、その原則は、次回の推定処理時間が最も短いプロセスを選択することであり、短いプロセスは長いジョブをスキップしてキューの先頭にジャンプします。

    • 最短残り時間 最初のスケジューリングアルゴリズム

    最短残り時間は、最初に最短のプロセスにプリエンプション機構を追加したバージョンです。この場合、プロセスのスケジューリングでは、予想される残り時間が最も短いプロセスが常に選択されます。プロセスが準備完了キューに追加されると、現在実行中のプロセスよりも残り時間が短い可能性があるため、スケジューラは、新しいプロセスの準備が整うとすぐに、現在実行中のプロセスを先取りできる可能性があります。最短プロセス優先と同様に、スケジューラーは、処理時間を見積もる必要がある選択機能を実行しているため、プロセスが長時間枯渇する危険性があります。

    • 高応答率優先スケジューリングアルゴリズム

    高応答率優先スケジューリング アルゴリズムは、主にジョブ スケジューリングに使用されます.このアルゴリズムは、各ジョブの待機時間と推定実行時間を考慮しながら、先着順スケジューリング アルゴリズムと短いジョブ優先スケジューリング アルゴリズムを総合的にバランスさせたものです. 各ジョブのスケジューリングでは、まずバックアップジョブキュー内の各ジョブの応答率を計算し、応答率が最も高いジョブを選択して実行します。

    • 優先スケジューリングアルゴリズム

    優先度スケジューリング アルゴリズムは、毎回バックアップ ジョブ キューから最も優先度の高い 1 つまたは複数のジョブを選択し、それらをメモリに転送し、必要なリソースを割り当て、プロセスを作成して準備完了キューに入れます。プロセススケジューリングでは、プライオリティスケジューリングアルゴリズムにより、毎回レディキューから優先度の最も高いプロセスを選択し、プロセッサを割り当てて動作させます。

4. ディスクスケジューリングアルゴリズム

  1. ディスク スケジューリング アルゴリズムの詳細な紹介

    一般的なディスク スケジューリング アルゴリズムは次のとおりです。

    • 先着順アルゴリズム
    • 最短シーク時間の最初のアルゴリズム
    • スキャンアルゴリズム
    • サイクルスキャンアルゴリズム
    • LOOK および C-LOOK アルゴリズム

    先着順

    First-Come, First-Served ( First-Come, First-Served, FCFS ) は、名前が示すように、最初に来た要求が最初に処理されます。

    最初に最短シーク時間

    最短シーク時間優先 ( Shortest Seek First、SSF ) アルゴリズムは、現在のヘッド位置からシーク時間が最短のリクエストを優先的に選択することで機能します。

    スキャンアルゴリズム

    最短シーク時間優先アルゴリズムがスタベーションを引き起こす理由は、磁気ヘッドが狭い領域で前後に移動する可能性があるためです。

    この問題を防ぐために、ヘッドが一方向に移動し、すべての未処理の要求にアクセスし、ヘッドがその方向の最後のトラックに到達するまで方向を変えないことを規定できます. これがスキャン (*スキャン*) です。アルゴリズム

    このアルゴリズムはエレベータ アルゴリズムとも呼ばれ、たとえば、エレベータはある方向に要求がなくなるまでその方向に移動し続け、その後方向を変えます。

    サイクルスキャンアルゴリズム

    スキャン アルゴリズムは各トラックの応答周波数を異なるものにするため、この問題を最適化するには、常に同じ方向にスキャンして、各トラックの応答周波数が基本的に同じになるようにします。

    Circular Scan ( CSCAN ) は、ヘッドが特定の方向に移動した場合にのみトラック アクセス要求が処理され、戻るときに最端のトラックに直接移動する、つまりヘッドをリセットすることを規定しており、このプロセスは非常に高速です。このアルゴリズムの特徴は、トラックが一方向のリクエストにのみ応答することです。

    LOOK および C-LOOK アルゴリズム

    スキャニング アルゴリズムとサイクリック スキャン アルゴリズムでは、どちらのヘッドも方向転換を開始する前にディスクの「先頭または末尾」に移動します。

    次に、これを実際に最適化することができます. 最適化の考え方は、ヘッドが「最も遠い要求」の位置に移動し、その後すぐに反対方向に移動することです.

    SCAN アルゴリズムの最適化は、LOOK アルゴリズムと呼ばれ、ヘッドは各方向で要求された最も遠い位置にのみ移動し、ディスクの最初または最後に移動することなく、すぐに反対方向に移動します。移動中にreverse Requestに応答します

    C-SCAN アルゴリズムの最適化は C-LOOK と呼ばれ、その動作方法では、ヘッドは各方向で要求された最も遠い位置にのみ移動し、その後すぐに反対方向に移動し、最初または最後には移動しません。ディスク、逆方向の移動中はリクエストに応答しません

5. ページ置換アルゴリズム

  1. ページ置換アルゴリズムの詳細

    オンデマンド ページングとも呼ばれるデマンド ページングは​​、メモリ内にない「ページ」が、プロセスの実行中に必要な場合にのみ呼び出されることを意味します。それ以外の場合は、プログラムの最後に呼び出されない可能性があります。ただし、メモリ内のページ用に予約されたスペースは限られており、ページはメモリ内のフレーム単位で配置されます。要求ページングのプロセスでメモリ ページ フォールトが多すぎるのを防ぐため (つまり、必要なページが現在メモリ内になく、データをハードディスクから読み取る必要がある、つまりページを置き換える必要がある)。 ) とプログラムの実行効率が低下する場合, ページ置換アルゴリズムを設計する必要があります. これらのアルゴリズムに従ってページを相互に置換すると、エラー率をできるだけ低くすることができます. 一般的に使用されるページ置換アルゴリズムは次のとおりです。

    • 先入れ先出し置換アルゴリズム (FIFO)

    先入れ先出し、つまり、最も早くロードされたページを除外します。

    • 最適順列アルゴリズム (OPT)

    将来最も使用されるページを選択して削除することが最適なソリューションであり、欠落ページの数が最も少ないことを証明できます。

    • 最近使用されていない (LRU) アルゴリズム

    つまり、最も長く使用されていないページを選択して削除します

    • クロック置換アルゴリズム

    クロック置換アルゴリズムは、NRU (最近使用されていません) とも呼ばれます。このアルゴリズムは、各ページにアクセス ビットを設定し、メモリ内のすべてのページをリンク ポインターを通じて循環キューにリンクします。

6. ネットワークシステム

  1. ゼロコピーとは

    ファイル転送のパフォーマンスを向上させるために、sendfileディスク読み取りとネットワーク送信の2つの操作をシステムコール(メソッド)で組み合わせ、コンテキストスイッチの回数を減らすゼロコピー技術が登場しました。さらに、データのコピーはカーネル内で行われるため、データのコピーの数は自然に減少します。

    Kafka と Nginx の両方がゼロコピー テクノロジを実装しているため、ファイル転送のパフォーマンスが大幅に向上します。

    ゼロコピー技術は PageCache に基づいています. PageCache は最近アクセスされたデータをキャッシュし、キャッシュされたデータへのアクセスのパフォーマンスを向上させます. 同時に、機械式ハードディスクの遅いアドレス指定の問題を解決するために、I/O も支援します. IO マージと事前認識を実現するスケジューリング アルゴリズム. これが、シーケンシャル リードがランダム リードよりも優れたパフォーマンスを発揮する理由です。これらの利点により、ゼロコピーのパフォーマンスがさらに向上します。

  2. I/O 多重化

    リクエストごとにプロセス/スレッドを割り当てるのは不適切なので、1 つのプロセスだけを使用して複数のソケットを維持することは可能ですか? 答えはイエスです。それがI/O 多重化テクノロジーです。

    プロセスは一度に 1 つのリクエストしか処理できませんが、各リクエストのイベントを処理するのにかかる時間は 1 ミリ秒未満であるため、1 秒以内に数千のリクエストを処理できます。この考え方は、複数のプロセスを同時に実行する CPU に非常に似ているため、時分割多重化とも呼ばれます。

    私たちがよく知っているselect/poll/epollカーネルは、ユーザーモード用の多重化システムコールを提供し、プロセスはシステムコール関数を介してカーネルから複数のイベントを取得できます

    select/poll/epoll はどのようにネットワーク イベントを取得しますか? イベントを取得するときは、まずすべての接続 (ファイル記述子) をカーネルに渡し、カーネルはイベントを生成した接続を返し、これらの接続に対応する要求をユーザー モードで処理します。

  3. 選択/ポーリング/epoll

    select と poll の間に本質的な違いはありません. どちらも内部的に "線形構造" を使用して、プロセスが関心を持つ Socket コレクションを格納します。

    これを使用する場合、最初に対象の Socket コレクションをユーザー状態からカーネル状態に select/poll システム コールを介してコピーする必要があり、その後カーネルがイベントを検出します. ネットワーク イベントが発生すると、カーネルはプロセスをトラバースする必要があります。 Socket コレクションに注意を払い、対応する Socket を見つけ、そのステータスを読み取り/書き込み可能に設定してから、Socket コレクション全体をカーネル状態からユーザー状態にコピーすると、ユーザー状態は引き続き Socket コレクション全体をトラバースします。読み取り/書き込み可能なソケットを見つけて処理します。

    明らかに、select と poll の欠点は、クライアントが多い場合、つまり Socket コレクションが大きい場合、Socket コレクションのトラバーサルとコピーが多くのオーバーヘッドをもたらすため、C10K を処理するのが難しいことです。

    epoll は、C10K 問題を解決するための強力なツールであり、選択/ポーリングの問題を 2 つの方法で解決します。

    • epoll はカーネル内の「赤黒ツリー」を使用して、プロセスで検出されるすべてのソケットに焦点を当てます. 赤黒ツリーは効率的なデータ構造です. 追加、削除、および変更の一般的な時間の複雑さは O(この黒赤ツリーの管理により、select/poll などの操作ごとに Socket コレクション全体を渡す必要がなくなり、カーネルとユーザー空間での大量のデータ コピーとメモリ割り当てが削減されます。
    • epoll はイベント ドリブン メカニズムを使用します. 準備完了イベントを記録するために "リンク リスト" がカーネルで維持されます. イベントが発生したソケット コレクションのみがアプリケーションに渡されます. select のようにコレクション全体をポーリングしてスキャンする必要はありません. /poll (yes と no を含む) Event Socket) を使用すると、検出効率が大幅に向上します。

    さらに、epoll はエッジ トリガーと水平トリガーをサポートしますが、select/poll は水平トリガーのみをサポートします. 一般的に、エッジ トリガーは水平トリガーよりも効率的です。

  4. 高性能ネットワーク モード: Reactor および Proactor

    3 つの一般的な Reactor 実装があります。

    最初の解決策は、プロセス間通信とデータ同期を考慮しない単一の Reactor 単一プロセス/スレッドであるため、実装が比較的簡単ですが、この解決策の欠点は、マルチコア CPU をフルに活用できないことです。 for processing business logic cannot be too long. そうしないと、応答が遅くなるため、コンピューターを多用するシナリオには適していませんが、ビジネス処理が高速なシナリオには適しています. たとえば、Redis (6.0 より前) は単一リアクターを使用しますシングルプロセスソリューション。

    2 番目の解決策は単一の Reactor マルチスレッド化で、これは最初の解決策の欠点をマルチスレッド化によって解決しますが、まだ高い同時実行性にはほど遠い. 違いは、監視して応答する Reactor オブジェクトが 1 つしかないことです.すべてのイベント、およびスレッドで実行されているメインでのみ、瞬間的な高同時実行シナリオに直面すると、パフォーマンスのボトルネックになりやすいです。

    3 つ目の解決策は、複数の Reactor を介して 2 つ目の解決策の欠点を解決するマルチリアクター マルチプロセス/スレッドです. メインの Reactor はイベントの監視のみを担当し、イベントに応答する作業はスレーブの Reactor に引き渡されます。 Netty も Memcache も「マルチリアクター マルチスレッド」方式を採用していますが、Nginx は「マルチリアクター マルチプロセス」に似た方式を採用しています。

    Reactor は、「オペレーティング システムがアプリケーション プロセスにイベントを通知し、アプリケーション プロセスにそれを処理させる」と理解できます。一方、Proactor は、「オペレーティング システムがイベントを処理し、イベントが処理された後にアプリケーション プロセスに通知する」と理解できます。

    したがって、本当の大きなキラーは、非同期 I/O によって実装された非同期ネットワーク モデルである Proactor であり、完了した読み取りおよび書き込みイベントを認識し、Reactor のようにイベントを感知した後にカーネルから読み取るために read を呼び出す必要はありません。からデータを取得します。

    ただし、Reactor と Proactor はどちらも「イベント分散」に基づくネットワーク プログラミング モデルです. 違いは、Reactor モデルは「完了予定」の I/O イベントに基づいているのに対し、Proactor モデルは「完了した」I/O イベントに基づいていることです。 〇イベント。

  5. コンシステント ハッシュの概要

    コンシステント ハッシュとは、"ストレージ ノード" と "データ" の両方をエンド ツー エンドのハッシュ リングにマッピングすることを指します. ノードが追加または削除された場合、ハッシュ リング上のノードの時計回りに隣接する後続ノードのみが影響を受けます. ノード,他のデータは影響を受けません。

    しかし、コンシステント ハッシュ アルゴリズムではノードを均等に分散できず、大量のリクエストが 1 つのノードに集中することになり、災害復旧や容量拡張を行う際に雪崩の連鎖反応が発生しやすくなります。

    コンシステント ハッシュ アルゴリズムではノードを均等に分散できないという問題を解決するには、仮想ノードを導入し、実ノードの複数のコピーを作成する必要があります。実際のノードをハッシュ リングにマッピングする代わりに、仮想ノードをハッシュ リングにマッピングし、仮想ノードを実際のノードにマッピングするため、「2 層」のマッピングが存在します。

    仮想ノードの導入により、ノードのバランスが改善され、システムの安定性も向上します。したがって、仮想ノードを使用したコンシステント ハッシュ方式は、ハードウェア構成が異なるノードを使用するシナリオだけでなく、ノードのサイズが変化するシナリオにも適しています。

7. ロック

  1. デッドロックとは何か、デッドロックの原因

    デッドロックとは、動作中に複数のプロセスがリソースを奪い合い、デッドロック状態になることを指し、プロセスがデッドロック状態になると、プロセスは外力なしでは前に進むことができなくなります。下図のように、既にロック A を保持しているスレッド A がロック B を取得しようとし、スレッド B がロック B を保持しながらロック A を取得しようとすると、この場合デッドロックが発生します。

    デッドロックの原因

    システムには譲渡できないリソースがいくつかあるため、2 つ以上のプロセスが独自のリソースを占有し、互いのリソースを要求すると、各プロセスは前進できなくなり、デッドロックが発生します。

    • 競合するリソース

    たとえば、システムにはプロセス A が使用できるプリンターが 1 つしかなく、A がプリンターを占有していると仮定すると、B がプリンターに印刷を要求し続けると、ブロックされます。

    システム内のリソースは、次の 2 つのカテゴリに分けることができます。

    1. 剥奪可能なリソース: プロセスがそのようなリソースを取得した後、そのリソースは他のプロセスまたはシステムによって剥奪される可能性があります.CPU とメイン メモリはどちらも剥奪可能なリソースです。
    2. 譲渡不可能なリソース. システムがそのようなリソースをプロセスに割り当てた場合、それらを強制的に取り戻すことはできませんが、テープ ドライブやプリンターなど、プロセスが使い果たされた後にのみ解放することができます。
    • プロセスの進行が乱れている

    例: プロセス A とプロセス B が互いのデータを待機しています。

    デッドロックが発生するための必要条件は?

    1. 相互に排他的な条件: プロセスは、割り当てられたリソースを排他的に制御する必要があります。つまり、特定のリソースは、一定期間内に 1 つのプロセスによってのみ占有されます。
    2. 要求と保留の条件: プロセスがリソースの要求によってブロックされている場合、プロセスが獲得したリソースを保留します。
    3. 非剥奪条件: プロセスによって取得されたリソースは、使い切られる前に剥奪することができず、使い切られたときにのみ自分で解放できます。
    4. 循環待機条件: デッドロックが発生した場合、プロセス リソースの循環チェーンが存在する必要があります。
  2. デッドロックを回避する方法

    デッドロック防止、デッドロック回避、デッドロック検出、デッドロック除去

    デッドロック防止

    1. リクエスト条件を破棄します。すべてのリソースを一度に割り当てて、それ以上リクエストがないようにします。
    2. 破棄の条件を守ってください: 1 つのリソースを割り当てることができない限り、他のリソースはこのプロセスに割り当てられません:
    3. 不可分条件の解除: プロセスが一部のリソースを取得しても他のリソースを取得できない場合、占有されているリソースは解放されます。
    4. ループ待機状態の打破: システムはリソースの種類ごとに番号を割り当て、各プロセスは番号の昇順でリソースを要求し、解放はその逆です。

    デッドロックを取り除く

    1. リソースの剥奪: デッドロックされたプロセスを一時停止し、そのリソースを先取りし、これらのリソースを他のデッドロックされたプロセスに割り当てます (ただし、一時停止されたプロセスがリソースを長時間取得するのを防ぐ必要があります)。
    2. キャンセル プロセス: デッドロック プロセスの一部またはすべてを強制的にキャンセルし、これらのプロセスからリソースを奪います (キャンセルの原則は、プロセスの優先度とプロセスをキャンセルするコストに従って実行できます)。
    3. プロセスのロールバック: デッドロックを回避するのに十分な 1 つ以上のプロセスをロールバックします。リソースは、剥奪されるのではなく、プロセスがロールバックするときに自発的に解放されます。システムは、プロセスの履歴情報を保持し、復元ポイントを設定する必要があります。
  3. 悲観ロック、楽観ロックとは

    悲観的ロックはより悲観的です. 複数のスレッドが同時に共有リソースを変更する可能性が比較的高いと考えられているため, 競合が発生しやすい. したがって, 共有リソースにアクセスする前に, まずそれらをロックしてください.

    楽観的ロックはより楽観的に動作します. 競合の可能性が非常に低いことを前提としています. その動作方法は次のとおりです: まず共有リソースを変更し, 次にこの期間中に競合がないかどうかを確認します. 他のスレッドがリソースを変更していない場合,他のスレッドがこのリソースを変更したことが判明した場合、操作は中止されます

    楽観的ロックの考え方は、何が起こってもリソースが最初に変更されるというものであることがわかります。さらに、楽観的ロックはプロセス全体でロックされないため、ロックフリー プログラミングとも呼ばれます

    ミューテックス ロック、スピン ロック、読み書きロックはすべてペシミスティック ロックです。

  4. 食の哲学者問題

    生産者と消費者の問題の説明:

    • プロデューサがデータを生成した後、データはバッファに配置されます。
    • コンシューマーは、処理のためにバッファーからデータをフェッチします。
    • 常に1 つのプロデューサーまたはコンシューマーのみがバッファーにアクセスできます。

    問題の分析から、次のように結論付けることができます。

    • バッファを操作できるスレッドは常に 1 つだけです。これは、バッファの操作が重要なコードであり、相互排除が必要であることを示しています。
    • バッファーが空の場合、コンシューマーはプロデューサーがデータを生成するのを待つ必要があり、バッファーがいっぱいの場合、プロデューサーはコンシューマーがデータをフェッチするのを待つ必要があります。プロデューサーとコンシューマーを同期させる必要があることを説明します。

    次に、次の 3 つのセマフォが必要です。

    • 相互排他セマフォmutex: バッファーへの相互排他アクセスに使用されます。初期値は 1 です。
    • リソースセマフォfullBuffers: コンシューマがバッファにデータがあるかどうかを尋ね、データがある場合はデータを読み取るために使用され、初期化値は 0 (バッファが最初は空であることを示します) です。
    • リソースセマフォemptyBuffers: 生産者がバッファーにスペースがあるかどうかを尋ね、スペースがあればデータを生成するために使用され、初期化値は n (バッファーサイズ) です。

    コンシューマ スレッドが実行を開始するとP(fullBuffers)、セマフォのfullBuffers初期、fullBuffersこの時点で の値は 0 から -1 に変化し、バッファにデータがなく、コンシューマは待機しかできないことを示します。

    次に、プロデューサが execute の番ですP(emptyBuffers)。つまり、空きスロットが 1 つ減ります。現在、クリティカル セクションでコードを実行しているプロデューサ スレッドが他にない場合、プロデューサ スレッドはデータをバッファに入れることができます。データを入れた後、セマフォを実行しますV(fullBuffers)fullBuffers -1 から 0 の場合、「コンシューマー」スレッドがブロックしてデータを待機していることを示します。そのため、ブロックされた待機中のコンシューマー スレッドが起動されます。

    コンシューマ スレッドが起動された後、この時点で他のコンシューマ スレッドがデータを読み取っていない場合は、クリティカル セクションに直接入り、バッファからデータを読み取ることができます。最後に、クリティカル セクションを離れた後、空きスロットの数に 1 を追加します。

  5. 生産者消費者問題

    食事の哲学者のための問題文:

    • 5兄貴の哲学者は、何もすることがなく、円卓の周りで麺を食べています。
    • 偶然にも、このテーブルには54 つの、2 人の哲学者ごとに 1 つのフォークが配置されています。
    • 哲学者は集まってまず考え、考えている途中でお腹が空いたら食べたくなる。
    • これらの哲学者は、麺類を喜んで食べるために 2 つのフォークを必要とします。
    • 食べた後、2本のフォークを元の位置に戻し、考え続けます。

    1. 偶数の哲学者は「最初に左のフォークを取り、次に右のフォークを取る」ようにし、奇数の哲学者は「最初に右のフォークを取り、次に左のフォークを取る」ようにします。

    P作戦では、哲学者の数に応じて、左右のフォークを拾う順番が異なります。さらに、V 操作はブロックしないため、V 操作は分岐を必要としません。

    2. アレイ状態を使用して、各哲学者の 3 つの状態 (食事状態、思考状態、空腹状態 (フォークを握ろうとする)) を記録します。

    次に、哲学者は、両方の隣人が食べていない場合にのみ、食べる状態に入ることができます.

    上記のプログラムは、必要なフォークが占有されている間、食事をしたい哲学者がブロックされるように、各哲学者に 1 つずつセマフォの配列を使用します。

  6. リーダーライターの問題

    リーダーはデータを読み取ることしかできず、データを変更することはできませんが、ライターはデータを読み取って変更することができます。

    リーダーライター問題の説明:

    • 「読み取り-読み取り」により、複数のリーダーが同時に読み取ることができます。
    • 「読み書き」相互排除: ライターがいない場合、リーダーは読み取り可能であり、リーダーが存在しない場合、ライターは書き込み可能
    • 「書き込み-書き込み」の相互排除: ライターは、他のライターがいない場合にのみ書き込むことができます

    セマフォを使用して解決を試みます。

    • Semaphore wMutex: 書き込み操作を制御する相互排除セマフォ。初期値は 1 です。
    • Reader count rCount: 読んでいる読者の数。0 に初期化されます。
    • Semaphore rCountMutex: rCount リーダー カウンターの相互に排他的な変更を制御します。初期値は 1 です。

    この実装はリーダー ファースト戦略であり、読んでいるリーダーがいる限り、後続のリーダーが直接入ることができます. リーダーが入り続けると、ライターは飢餓状態になります.

    リーダー ファーストの戦略があるため、ライター ファーストの戦略もあります。

    • ライターが書き込みの準備ができている限り、ライターはできるだけ早く書き込み操作を実行する必要があり、後続のリーダーはブロックする必要があります。
    • 書き続ける作家がいれば、読者は飢えています。

    スキーム 1 に基づいて次の変数を追加します。

    • Semaphore rMutex: リーダーが入るように制御する相互排除セマフォ。初期値は 1 です。
    • Semaphore wDataMutex: ライターの書き込み操作を制御する相互排除セマフォ。初期値は 1 です。
    • Writer count wCount: ライターの数を記録します。初期値は 0 です。
    • Semaphore wCountMutex: wCount の相互排他的な変更を制御します。初期値は 1 です。

    rMutexここでの効果は, 複数のリーダーがデータの読み取りを開始し, それらすべてがリーダーキューに入ることに注意してください. このとき, ライターが来るP(rMutex). の実行後, 後続のリーダーは でブロックさrMutex、すべてライターキューに入ることができるため、ライターの優先度が保証されます。

    同時に、最初のライターが を実行しP(rMutex)た後、すぐに書き込みを開始することはできず、リーダー キューに入っているすべてのリーダーが読み取り操作を完了するまで待ってから、V(wDataMutex)ライターを起動して書き込みを行う必要があります。

    リーダーファースト戦略もライターファースト戦略も飢餓を引き起こすので、公正な戦略を実装しましょう。

    公正な戦略:

    • 同じ優先度;
    • ライターとリーダーの相互排他的アクセス。
    • クリティカル セクションにアクセスできるライターは 1 人だけです。
    • 複数のリーダーが重要なリソースに同時にアクセスできます。

8. オペレーティング システムの知識ポイント

  1. 並行性と並列性の理解

    1. 並列とは、2 つ以上のイベントが同時に発生することを意味し、同時実行とは、2 つ以上のイベントが同じ時間間隔で発生することを意味します。
    2. 並列処理は異なるエンティティでの複数のイベントであり、同時実行は同じエンティティでの複数のイベントです。
  2. ユーザーモードとカーネルモードとは

    ユーザー モードとカーネル モードは、オペレーティング システムの 2 つの動作状態です。

    • 内核态: カーネル状態の CPU は、ネットワーク カード、ハードディスクなどの周辺機器を含むすべてのデータにアクセスできます。カーネル状態の CPU は、あるプログラムから別のプログラムに切り替えることができ、CPU を占有してもプリエンプションは発生しません。一般に、特権レベルで 0 の状態はカーネル状態と呼ばれます。
    • 用户态:ユーザモードのCPUはアクセス制限のあるメモリしかアクセスできず、周辺機器へのアクセスは許可されず、ユーザモードのCPUは占有できないため、他のプログラムがCPUを占有することができません。
  3. 局所性の2つの原則とは.

    主に時間的局所性と空間的局所性に分けられます

    **時間局所性:** プログラム内の命令が実行されると、すぐに再び実行される可能性が高く、特定のデータがアクセスされると、そのデータはすぐに再びアクセスされる可能性があります。(プログラムにループが多いため)

    **空間的局所性:** プログラムが特定のストレージ ユニットにアクセスすると、その近くのストレージ ユニットはすぐにアクセスされる可能性があります。(大量のデータが連続してメモリに格納され、プログラムの命令も順次メモリに格納されるため)

  4. 例外と割り込みとは何ですか、また違いは何ですか

    邪魔をして

    キーボードでタイピングしているときに割り込みが発生し、ハードディスクがデータの読み書きを完了するときにも割り込みが発生する.したがって、割り込みがハードウェアデバイスによって生成されることを知る必要があります。物理的な電気信号であり、割り込みコントローラを介してCPUに送られ、CPUは受信した割り込みがどのハードウェアデバイスからのものかを判断し(これはカーネルで定義されています)、最後にCPUがそれをカーネルに送り、カーネルが割り込みを処理します。

    異常な

    CPU がプログラムを処理するとき、プログラムがメモリにない場合はページ フォールト例外が発生し、除算プログラムが実行されている場合、除数が 0 の場合は 0 による除算例外が発生します。したがって、例外はCPUによって生成され、同時にカーネルに送信され、カーネルにこれらの例外の処理を依頼することも覚えておく必要があります

    同点

    • 最後に、CPU によってカーネルに送信され、カーネルによって処理されます。
    • プロセッサ フローの設計は類似している

    違い

    • ソースが異なり、例外は CPU によって生成され、割り込みはハードウェア デバイスによって生成されます。
    • カーネルは、例外か割り込みかに応じて異なるハンドラーを呼び出す必要があります
    • 割り込みはクロック同期ではありません。つまり、割り込みはいつでも発生する可能性があります。例外は CPU によって生成されるため、クロック同期です。
    • 割り込みを処理するときは割り込みコンテキストで、例外を処理するときはプロセス コンテキストで
  5. アトミック操作

    **プロセッサは、キャッシュのロックまたはバスのロックに基づく方法を使用して、複数のプロセッサ間のアトミック操作を実装します。**まず、プロセッサは基本的なメモリ操作の原子性を自動的に保証します。プロセッサは、システム メモリからのバイトの読み取りまたは書き込みがアトミックであることを保証します。つまり、1 つのプロセッサがバイトを読み取ると、他のプロセッサはそのバイトのメモリ アドレスにアクセスできません。Pentium 6 および最新のプロセッサは、単一のプロセッサが同じキャッシュ ライン内の 16/32/64 ビットでアトミック操作を実行することを自動的に保証できますが、複雑なメモリ操作プロセッサは、バス幅全体、複数のプロセッサ間のアクセスなど、そのアトミック性を自動的に保証できません。キャッシュラインとページテーブル全体。ただし、プロセッサーはバス・ロックとキャッシュ・ロックの 2 つのメカニズムを提供して、複雑なメモリー操作の原子性を保証します。

    (1) バスロックによるアトミック性の確保 一つ目の仕組みは、バスロックによるアトミック性の確保です。

    いわゆるバスロックとは、プロセッサが提供する LOCK# 信号を使用することで、プロセッサがこの信号をバス上に出力すると、他のプロセッサの要求がブロックされるため、プロセッサは共有メモリを独占できます。

    (2) キャッシュロックを使用して原子性を確保する 2 つ目のメカニズムは、キャッシュロックによって原子性を確保することです。

  6. サーバーの高同時実行ソリューション

    • アプリデータと静的リソースの分離 静的リソース(写真、動画、js、cssなど)は別途専用の静的リソースサーバーに保存し、クライアントからのアクセス時に静的リソースサーバーから静的リソースを返却し、メインからアプリを返却するサーバーデータ。
    • クライアント側のキャッシュは最も効率が高く、リソースの消費が最も少ないのは純粋な静的 html ページであるため、Web サイトのページは可能な限り静的に実装でき、ページの有効期限が切れるかデータが失われた後にページが再キャッシュされます。更新されます。または、最初に静的ページを生成し、次に ajax 非同期リクエストを使用して動的データを取得します。
    • クラスタリングと分散 (クラスタリングとは、すべてのサーバーが同じ機能を持ち、主にシャントのために要求できることを意味します)
      (分散とは、異なるサービスを異なるサーバーに配置し、要求を処理するために複数のサーバーを使用して要求処理を高速化する必要がある場合があることを意味します) .)
      サーバー クラスタと分散アーキテクチャを使用して、元々 1 つのサーバーに属していたコンピューティング プレッシャーを複数のサーバーに分散できます。同時に、リクエスト処理を高速化します。
    • リバース プロキシがサーバーにアクセスすると、サーバーは他のサーバーからリソースまたは結果を取得し、それらをクライアントに返します。
  7. ジッターって知ってる?バンプ現象とも呼ばれる

    The page that has just been swapped out will be swapped into memory immediately, and the page that just has been swapped in will be swapped out of external memory immediately. この頻繁なページング動作は、ジッターまたはスラッシングと呼ばれます。ジッターの主な理由は、プロセスによって頻繁にアクセスされるページの数が、使用可能な物理ブロックの数よりも多い (プロセスに十分な物理ブロックが割り当てられていない) ことです。

    プロセスに割り当てられた物理ブロックが少なすぎると、プロセスがスラッシングします。プロセスに割り当てられた物理ブロックが多すぎると、システム全体の同時実行性が低下し、特定のリソースの使用率が低下します.各プロセスに割り当てられる物理ブロックの数を研究するために、デニングは「プロセスワーキングセット」の概念を提案しました.

おすすめ

転載: blog.csdn.net/weixin_53795646/article/details/129540908