38

sleep(time in ms)Cライブラリまたは基本的にOSレベルでどのように実装されているかに興味があります...

私は推測しています...

  1. nopのwhileループを実行するプロセッサ速度に基づいている可能性があります(スリープ時間が正確かどうかはわかりません)...
  2. プロセッサ内の任意の特殊レジスタ。値を書き込むと、プロセッサは指定された時間だけ停止します (プロセッサは他のプログラムでさえ実行できないため、これは非常に非効率的です)。

手がかりはありますか?おそらくCライブラリのソースコードで説明できますか? 「C」がそれをどのように実装しているかについてはあまり詳しくありません...一般的に「sleep()」関数がどのように実装されているのか疑問に思っています。

4

6 に答える 6

30

Sleep()OSレベルで実装されています。タスク/スレッド/プロセスがスリープ状態のとき、プロセッサは回転しません。その特定のスレッドは、スレッドが実行準備完了キューに置かれる時点で時間切れになるまで、保留キュー (スレッドは実行準備ができていない) に置かれます。

その間、実行準備ができている他のスレッドが実行されます。

実行する準備ができているスレッドがない場合にのみ、OS はアイドル スレッドに入ります。アイドル スレッドは通常、ハードウェア割り込みが発生するまで、プロセッサをシャットダウンする (またはとにかく低電力状態にする) 命令を発行します。

非常に単純なシステム (最も単純な組み込みシステムなど) の場合にのみ、Sleep() 実際にはビジー待機ループに過ぎないものとして実装される場合があります。

Tanenbaum による "Modern Operating Systems"などのオペレーティング システムの教科書では、これについて非常に詳細に説明されています。

于 2009-11-12T00:38:14.150 に答える
3

あなたの質問に対する答えは、オペレーティング システムと実装に完全に依存します。

それについて考える簡単な方法: を呼び出すsleep()と、OS はウェイクアップ時間を計算し、プロセスをどこかの優先キューに入れます。その後、プロセスがキューからポップされるのに十分な時間が経過するまで、プロセスが実行時間を取得するようにスケジュールしません。

于 2009-11-12T00:38:55.163 に答える
3

典型的なオペレーティング システムでは、sleep はカーネルを呼び出します。カーネルは、指定された時間が経過するまで待機するようにプロセスを設定し、その後、実行する他のプロセスを見つけます。やるべきことが何もなければ、「アイドルプロセス」を実行します。時間が経過すると、スケジューラはスリープ プロセスが開始されたことを通知し、再度スケジュールを設定します。

于 2009-11-12T00:39:06.643 に答える
1

スリープは、渡された時間値の間、タスク/スレッドをブロックします。タスクは、その期間中、または別の興味深い何か (シグナルなど) が発生するまで、どちらか早い方で実行できなくなります。

スリープが select() を呼び出し、待機する記述子を渡さず、スリープ期間に等しいタイムアウト値を渡すことは珍しくありません。

システムは、時間が経過した後にタイマーが期限切れになるように設定し、そのタイマーが期限切れになったときに通知されるセマフォを待機することで、これを実装できます。したがって、そのセマフォでブロックされます。

于 2009-11-12T08:37:48.487 に答える
1

そうしないと、システムは何もできなくなります-マウス、キーボード、ネットワークなどに応答しません.

通常、ほとんどのオペレーティング システムでは、現在のタイムスタンプに遅延を追加して、遅延を要求したタスクが再開されるタイムスタンプを取得し (その時点で優先度の高いタスクが実行されていないと仮定して)、[wakeupTimestamp, タスク ポインター] を追加します。 ] をタイムスタンプの昇順で並べ替えたリストにします。その後、OS はコンテキスト スイッチを実行し、次に使用可能なタスクを実行します。定期的に、システムはスリープ リストの最も古いタイムスタンプと現在のタイムスタンプを比較し、期限が過ぎている場合は、スリープ タスクを「準備完了」タスク キューに移動します。

于 2009-11-12T00:38:57.690 に答える
1

cpu 使用率: 0%
要件:
create_gate (IRQ ハンドラーをセットアップする)
pic_mask_clear (特定の割り込みを有効にする)
rtc_poll (RTC をセットアップする)
rtc_irq
smp_wake_up

; In\   RAX = Time in millisecond
; Out\  All registers preserved
sleep:
    push rcx
    push rax

    mov rcx, [rtc_irq.up_time]
    add rax, rcx
.os_delay_loop:
    hlt
    cmp qword [rtc_irq.up_time], rax
    jle .os_delay_loop

    pop rax
    pop rcx
    ret

smp_wake_up

; In\   Nothing
; Out\  Nohting
smp_wakeup_all:
    push rdi
    push rax

    mov rdi, [os_LocalAPICAddress]
    xor eax, eax
    mov [rdi+0x0310], eax   ; Write to the high bits first
    mov eax, 0x000C0080 ; Execute interrupt 0x80
    mov [rdi+0x0300], eax   ; Then write to the low bits

    pop rax
    pop rdi
    ret

rtc_irq:

; UIP (0), RTC@32.768KHz (010), Rate@1024Hz (0110)
; In\   Nothing
; Out\  Nothing
rtc_irq:
    inc qword[.up_time]
    call smp_wakup_all
    ret
.up_time:       dq 0

利用方法 :

mov rax, 1000 (millisecond)
call sleep

大丈夫だよ

于 2018-03-27T13:43:32.310 に答える