pythonのsleep関数の実装を行っている以下のファイルを見ると、nanosleepやclock_nanosleep関数を用いて停止を行っていることがわかります。
ここで、nanosleepやclock_nanosleep関数はC言語のtime.hにおいて定義されている関数であり、UNIXシステムコールです。
nanosleepやclock_nanosleepなどのsleep関連のシステムコールを呼び出すとはどういうことなのかを理解するために、OSのやっていることについて少し説明します。
OSの重要な仕事はスレッドにCPUをわりあてることですが、ここでOSがCPUを各スレッドに「うまく」割り当てるために、OSはスレッドの3つの状態を区別します。その3つの状態とは、
- 実行中(Running)
- 実行可能(Runnable,active)
- 中断中(blocked,suspended)
です。
htopコマンドなどでスレッドの状態を確認してみるとわかりやすいです。以下の写真では、一つのスレッドがR(実行中 or 実行可能)で、他のスレッドはS(中断中)になっています。
ここでsleep関連システムコールの話に戻りますが、これらのシステムコールは「呼び出したスレッドの実行をn秒間停止する」というのが基本になります。
(一応シグナル割り込みとかその他の例外の話もあるらしいですが、まだそこまで理解してないのでここでは触れません)
スレッドが停止している間は上で触れたsuspended状態になり、そのスレッドは実行されません。(CPUを使用しない)
ということは、pythonのtime.sleep関数はこのシステムコールを呼んでいるだけですので、
sleep(n)
とすると、n秒間の間そのpythonスレッドは停止状態になり、CPUは使用しない、という動作になります。
なお、システムコールの話でsleepとnanosleepというものがでてきて少し紛らわしいのですが、sleep関数は引数にintをとるため整数秒停止させます。それに対しnanosleepでは引数にtimespecというデータ型をとり、ナノ秒刻みの時間停止を行うことができます。pythonのsleep関数ではnanosleep系のシステムコールを呼んでいるため、sleep(0.01)で0.01秒止める、みたいなことも可能になります。
参考