の続き。
第2章では、CPUはユーザモードとカーネルモードを切り替えて処理を実行しているということを学んだ。
CPUのモード遷移の図や実験で試したプログラムのCPUのモードの遷移図は分かりやすい。
試したコマンドは、strace
, sar
。
簡単なプログラムを書いて、「ユーザモードで動く場合」「カーネルモードで動く場合」のプロセスのモードの割合を確認した。
まだ難しくない内容なので、どんどん進めていこう。
ノート
第2章 ユーザモードで実現する機能
- 各種プロセスは、プロセス生成、ハードウェアの操作など、カーネルの助けが必要なときにはシステムコールという手段によってカーネルに処理を依頼する
- システムコール
- プロセス生成、削除
- メモリ確保、解放
- プロセス間通信
- ネットワーク
- ファイルシステム
- ファイル操作(デバイスアクセス)
- システムコールを発行すると、CPUにおいて割込みというイベントが発生する
- これにより、CPUではユーザモードからカーネルモードに依頼し、内容に応じてカーネルの処理が動く
- 処理が終われば、ユーザモードに戻りプロセスの動作を継続する
- straceの出力は、1つのシステムコール発行が1行に対応している
- sarコマンドでプロセスがユーザモードとカーネルモードのどちらで実行しているかの割合を取得できる
- sar -P ALL 1
- allになっている行は全CPUの平均値
- ユーザモードでプロセスを実行している割合は、%userと%niceの合計
- CPUコアが、カーネルモードでシステムコールなどの処理を実行している時間の割合は、「%system」によって得られる
- %idleはCPUコア上でプロセスもカーネルも動いていない状態
各行が1つのCPUに対応している サーバーは1CPUなので、一つ Average: CPU %user %nice %system %iowait %steal %idle Average: all 0.00 0.00 0.00 0.00 0.00 100.00 Average: 0 0.00 0.00 0.00 0.00 0.00 100.00
loop処理実行後 Linux 4.15.0-50-generic (133-130-123-136) 06/10/19 _x86_64_ (1 CPU) 21:51:46 CPU %user %nice %system %iowait %steal %idle 21:51:47 all 100.00 0.00 0.00 0.00 0.00 0.00 21:51:47 0 100.00 0.00 0.00 0.00 0.00 0.00 Average: CPU %user %nice %system %iowait %steal %idle Average: all 100.00 0.00 0.00 0.00 0.00 0.00 Average: 0 100.00 0.00 0.00 0.00 0.00 0.00
親プロセスのプロセスIDを得るシステムコールのループ処理実行後 sar -P ALL 1 1 Linux 4.15.0-50-generic (133-130-123-136) 06/10/19 _x86_64_ (1 CPU) 21:55:02 CPU %user %nice %system %iowait %steal %idle 21:55:03 all 46.46 0.00 53.54 0.00 0.00 0.00 21:55:03 0 46.46 0.00 53.54 0.00 0.00 0.00 Average: CPU %user %nice %system %iowait %steal %idle Average: all 46.46 0.00 53.54 0.00 0.00 0.00 Average: 0 46.46 0.00 53.54 0.00 0.00 0.00
- %systemが数十のような大きな値に似合っている場合は、むやみにシステムコールを発行しているか、システム負荷が高すぎる場合が多い
- straceに「-T」オプションをつけると、各種システムコールの処理にかかった時間をマイクロ秒の精度で採取できる
- システムコールは、通常の関数呼び出しとは違い、直接呼び出せない
- アーキテクチャ依存のアセンブリコードを使って呼び出す必要がある
- この問題を解決するために、OSは内部的にシステムコールを呼び出すだけの、システムコールラッパーと呼ばれる一連の関数を提供している
- https://twitter.com/_ryskit/status/1138069450014330881
- glibcは、システムコールのラッパー関数を含む
- ldd /bin/echo
- ldd ppidloop
- ldd /usr/bin/python3