46

今、私がいつも疑問に思っていることがあります。sleep()はどのように実装されていますか?

OSのAPIを使用することがすべての場合、APIはどのように作成されますか?

結局のところ、CPUで特別なマシンコードを使用することになりますか?そのCPUには、sleep()を使用できない特別なコプロセッサーまたはその他のギズモが必要ですか?

sleep()の最もよく知られている化身は、C(より正確には、GNUのlibcなどのCコンパイラに付属するライブラリ)ですが、今日のほとんどすべての言語に同等のものがありますが、一部の言語でのスリープの実装( Bash)は、この質問で私たちが見ているものではないと思います...

編集:いくつかの回答を読んだ後、プロセスが待機キューに入れられていることがわかります。そこから、私は2つの選択肢を推測することができます

  1. カーネルが期限内にプロセスをウェイクアップするようにタイマーが設定されている、または
  2. カーネルにタイムスライスが許可されている場合は常に、クロックをポーリングして、プロセスをウェイクアップする時間かどうかを確認します。

答えは代替案1についてのみ言及しています。したがって、私は尋ねます:このタイマーはどのように動作しますか?カーネルにプロセスをウェイクアップさせる単純な割り込みの場合、カーネルはタイマーに「プロセスを実行状態にできるように140ミリ秒でウェイクアップする」ようにどのように要求できますか?

4

8 に答える 8

43

質問の「更新」は、最新の OS の仕組みについての誤解を示しています。

カーネルはタイム スライスを「許可」されていません。カーネルは、ユーザー プロセスにタイム スライスを提供するものです。「タイマー」は、スリープ状態のプロセスを起動するようには設定されていません。現在実行中のプロセスを停止するように設定されています。

要するに、カーネルは、CPU 上に長時間置かれているプロセスを停止することによって、CPU 時間を公平に分配しようとします。簡単に説明すると、どのプロセスも 2 ミリ秒を超えて CPU を使用できないとします。したがって、カーネルはタイマーを 2 ミリ秒に設定し、プロセスを実行させます。タイマーが割り込みを発生させると、カーネルが制御を取得します。実行中のプロセスの現在の状態 (レジスタ、命令ポインターなど) を保存し、制御は戻りません。代わりに、CPU の割り当てを待機しているプロセスのリストから別のプロセスが選択され、中断されたプロセスはキューの最後に移動します。

スリープ中のプロセスは、CPU を待っているもののキューにありません。代わりに、スリープ キューに格納されます。カーネルがタイマー割り込みを受け取るたびに、スリープ キューがチェックされ、時間になったプロセスは「CPU 待ち」キューに転送されます。

もちろん、これは大幅な単純化です。セキュリティ、公平性、バランス、優先順位付け、飢餓の防止を確保するには、非常に洗練されたアルゴリズムが必要であり、カーネル データに使用されるメモリ量を最小限に抑えてすべてを高速に実行します。

于 2008-10-07T15:22:14.877 に答える
36

スリープ キューと呼ばれるカーネル データ構造があります。優先待ち行列です。プロセスがスリープ キューに追加されるたびに、最も早く起動されるプロセスの有効期限が計算され、タイマーが設定されます。その時点で、期限切れのジョブはキューから取り除かれ、プロセスは実行を再開します。

(面白いトリビア: 古い UNIX 実装では、 fork() が呼び出されたが、子プロセスが作成されていないプロセスのキューがありました。もちろん、それはfork queueと呼ばれていました。)

チッ!

于 2008-10-06T19:51:49.917 に答える
16

おそらく、オペレーティング システムの主な仕事は、実際のハードウェアの複雑さをアプリケーション作成者から隠すことです。したがって、OS がどのように機能するかを説明すると、非常に複雑になり、非常に高速になるリスクがあります。したがって、実際のオペレーティング システムが対処する必要があるすべての「もしも」や「ええと」を扱うつもりはありません。プロセスとは何か、プロセスとは何か、ということを高い概念レベルで説明するだけです。スケジューラーは、タイマー キューがどのように機能するかを説明します。

プロセスとは:

プロセスについて考えてみましょう - プロセスについてだけ話し、後でスレッドに行きましょう - 「オペレーティングシステムがスケジュールするもの」と考えてください。プロセスには ID があります (整数と考えてください)。その整数は、そのプロセスのすべてのコンテキストを含むテーブルへのインデックスと考えることができます。

コンテキストとは、ハードウェア情報 (レジスタ、メモリ管理ユニットの内容、その他のハードウェア状態) であり、マシンにロードされたときにプロセスを「実行」できるようにします。コンテキストの他のコンポーネントがあります-開いているファイルのリスト、シグナルハンドラーの状態、そしてここで最も重要なのは、プロセスが待機しているものです

プロセスは多くの時間をスリープ状態 (待機) に費やします

プロセスは待機に多くの時間を費やします。たとえば、ディスクの読み取りまたは書き込みを行うプロセスは、データが到着するか、ディスクに出力されたことを確認するために多くの時間を費やします。OS 関係者は、「待機中」と「スリープ中」(および「ブロック済み」) という用語をある程度同じ意味で使用します。これらはすべて、プロセスが楽しい道を進む前に何かが起こるのを待っていることを意味します。OS API の sleep() がたまたまスリープ プロセスの基礎となる OS メカニズムを使用していることは、混乱を招くだけです。

プロセスは、ネットワーク パケットの到着、ウィンドウ選択イベント、またはタイマーの期限切れなど、他のことを待機している可能性があります。

プロセスとスケジューリング

待機中のプロセスは、実行不可能であると言われます。オペレーティング システムの実行キューには入りません。しかし、プロセスが待機しているイベントが発生すると、オペレーティング システムはプロセスを実行不可能な状態から実行可能な状態に移行させます。同時に、オペレーティング システムはプロセスを実行キューに入れますが、これは実際にはキューではなく、オペレーティング システムがそうすることに決めた場合に実行できるすべてのプロセスの山です。

スケジューリング:

オペレーティング システムは、定期的にどのプロセスを実行するかを決定します。オペレーティング システムがそのようにすることを決定するアルゴリズムは、多少驚くことではありませんが、スケジューリング アルゴリズムと呼ばれます。スケジューリング アルゴリズムは、非常に単純なもの (「全員が 10 ミリ秒実行し、次にキューの次の人が実行する」) から、はるかに複雑なもの (プロセスの優先度、実行頻度、実行時間の締め切り、プロセス間の依存関係、連鎖ロック、およびその他のあらゆる種類の複雑な主題)。

タイマー キュー コンピュータにはタイマーが内蔵されています。これを実装する方法はたくさんありますが、古典的な方法は定期的なタイマーと呼ばれます。定期的なタイマーは一定の間隔で刻みます。今日のほとんどのオペレーティング システムでは、この速度は 1 秒あたり 100 回、100 Hz、10 ミリ秒ごとです。この値を以下の具体的なレートとして使用しますが、ほとんどのオペレーティング システムはさまざまなティックで構成できることを知っています。多くのオペレーティング システムはこのメカニズムを使用せず、はるかに優れたタイマー精度を提供できます。しかし、私は脱線します。

ティックごとに、オペレーティング システムへの割り込みが発生します。

OS がこのタイマー割り込みを処理するとき、システム時間の概念をさらに 10 ミリ秒増やします。次に、タイマー キューを調べて、そのキューのどのイベントを処理する必要があるかを判断します。

タイマー キューは、実際には「対処する必要があるもの」のキューであり、これをイベントと呼びます。このキューは、有効期限の時間順に並べられ、最も早いイベントが最初になります。

「イベント」は、「プロセス X をウェイクアップする」、「ディスク I/O が動かなくなった可能性があるため、あちらでキックする」、「あちらのファイバーチャネル リンクでキープアライブ パケットを送信する」などのようなものです。オペレーティングシステムが実行する必要があるものは何でも。

このように並べられたキューがある場合、デキューの管理は簡単です。OS は単純にキューの先頭を見て、イベントの「有効期限までの時間」をティックごとに 10 ミリ秒ずつ減らします。有効期限がゼロになると、OS はそのイベントをデキューし、必要な処理を実行します。

スリープ中のプロセスの場合、プロセスを再び実行可能にするだけです。

シンプルですね。

于 2008-10-07T01:34:44.733 に答える
10

この質問に答えるには、少なくとも 2 つの異なるレベルがあります。(そして、それと混同される他の多くのこと、私はそれらに触れません)

  1. アプリケーション レベルで、これが C ライブラリの機能です。これは単純な OS 呼び出しであり、時間が経過するまでこのプロセスに CPU 時間を与えないように OS に指示するだけです。OS には、中断されたアプリケーションのキューと、それらが何を待っているかに関する情報 (通常は、時間またはどこかに表示されるデータ) があります。

  2. カーネルレベル。OS が現在何もすることがない場合、OS は「hlt」命令を実行します。この命令は何もしませんが、それ自体で終了することはありません。もちろん、ハードウェア割り込みは正常に処理されます。簡単に言うと、OS のメイン ループは次のようになります (非常に遠くから)。

    allow_interrupts ();
    while (真) {
      ほら;
      check_todo_queues ();
    }
    

    割り込みハンドラは単に todo キューに追加するだけです。リアルタイム クロックは、定期的に (固定レートで) 割り込みを生成するか、次のプロセスが起動する必要がある将来の固定時間に割り込みを生成するようにプログラムされています。

于 2008-10-06T20:05:35.180 に答える
9

マルチタスクオペレーティングシステムにはスケジューラと呼ばれるコンポーネントがあり、このコンポーネントはスレッドに CPU 時間を与える責任があり、sleep を呼び出すと、しばらくの間このスレッドに CPU 時間を与えないように OS に指示します。

詳細については、 http://en.wikipedia.org/wiki/Process_statesを参照してください。

于 2008-10-06T19:53:57.417 に答える
8

Linux については何も知りませんが、Windows で何が起きているかはわかります。

Sleep() は、プロセスのタイム スライスをすぐに終了させ、制御を OS に戻します。次に、OS は、時間が経過した後に通知されるタイマー カーネル オブジェクトを設定します。OS は、カーネル オブジェクトが通知されるまで、そのプロセスにそれ以上の時間を与えません。それでも、他のプロセスがそれよりも優先度が高いか同等である場合は、プロセスを続行する前に少し待機することがあります。

OS は特別な CPU マシン コードを使用して、プロセスの切り替えを行います。これらの関数はユーザー モード コードからアクセスできないため、OS への API 呼び出しによって厳密にアクセスされます。

于 2008-10-06T19:56:22.187 に答える
5

基本的に、はい、「特別なギズモ」があります-そしてそれは単なるsleep()以上のものにとって重要です。

従来、x86では、これはIntel8253または8254の「プログラマブルインターバルタイマー」でした。初期のPCでは、これはマザーボード上の個別のチップであり、事前設定された時間間隔の後に割り込みをアサートするようにCPUによってプログラムできました(別の個別のチップである「ProgrammableInterruptController」を介して)。機能はまだ存在しますが、マザーボード回路のはるかに大きなチャンクのごく一部になっています。

現在のOSは、定期的にウェイクアップするようにPITをプログラムしています(最近のバージョンのLinuxでは、デフォルトで1ミリ秒に1回)。これにより、カーネルはプリエンプティブマルチタスクを実装できます。

于 2009-07-21T04:05:50.767 に答える