IOスケジューラとCPUスケジューラの概念は混乱しています。以下は私が理解したものです。
- Linux はデフォルトで CFS スケジューラ + nice 値を使用してプロセスをスケジュールします。
- 各プロセスにはIOキューがあります。
- IOスケジューラカーネルスレッドがあります。
- IOスケジューラはファイルレベルではなくブロックレベルにあります。
- IOスケジューラはファイルシステムのモジュールです。
質問:
IOスケジューラとCPUスケジューラの関係は何ですか?概念的には、CPUスケジューラはIOスケジューラよりも優れているようです。 CPU スケジューリングが最初に発生します。 IOスケジューラ自体はスレッドであり、CPUスケジューリングに従います。
人為的なシナリオは次のとおりです。
ステップ1:CPUスケジューラは実行のためにプロセスP1を選択します。
ステップ2:P1はIO要求を独自のIOキューに入れます。
ステップ3以上:CPUスケジューラは実行する別のスレッドを選択します。 (P1以外のプロセスにIOがないと仮定)
....(しばらくしてから)
ステップ:CPUスケジューラは、実行するIOスケジューラスレッドを選択します。
ステップn+1:IOスケジューラスレッドは、待機中のIO要求があることをP1に「通知」し、これらの要求をディスクに送信します。
私の理解とシナリオは意味がありますか?
答え1
IOスケジューラから始めましょう。各ブロックデバイスにはIOスケジューラがあります。その役割は、デバイスのキューに蓄積される要求を予約(ソート)することです。 Linuxカーネルは現在deadline
、noop
および3つのアルゴリズムを提供しますcfq
。cfq
マニュアルによると、デフォルト値は次のとおりです。
CFQ I/Oスケジューラは、システム内のすべてのプロセスに帯域幅を均等に配布しようとします。デスクトップおよびサーバーシステムに適した公平で遅延時間の短い作業環境を提供する必要があります。
scheduler
ブロックデバイスに対応するファイルを使用すると、どのスケジューラがどのデバイスを管理しているかを設定できます/sys/
(次のコマンドを実行して見つけることができます。)find /sys | grep queue/scheduler
。
この短い説明では、これがプロセスを調べるcfq
唯一のスケジューラであることを説明していません。プロセスに割り当てることができる設定であり、アルゴリズムは他の要求を選択する前にこれを考慮します。ユーティリティで設定できます。ioprio
ioprio
ioprio
ionice
その後、タスクスケジューラがあります。その役割は、プロセス間でCPUを配布することです。走る準備ができた。これは、特定のプロセスの優先順位、クラス、卓越性、およびプロセスが実行された期間、およびその他のヒューリスティックなどの要因を考慮に入れます。
今、あなたの質問に答えるには:
IOスケジューラとCPUスケジューラの関係は何ですか?
名前以外は何もありません。彼らはさまざまな共有リソースを準備します。最初の命令はディスクに要求を送信し、2番目の命令はCPUへの「要求」(プロセスを実行するためにCPU時間を要求すると考えることができます)をスケジュールします。
CPU スケジューリングが最初に発生します。 IOスケジューラ自体はスレッドであり、CPUスケジューリングに従います。
IOスケジューラアルゴリズムは、要求を待機しているプロセスによって実行されるようには発生しません。これを理解する良い方法は、elv_add_request()
そのパスで発生する競合を調べることです。例えば:
[...]
[<c027fac4>] error_code+0x74/0x7c
[<c019ed65>] elv_next_request+0x6b/0x116
[<e08335db>] scsi_request_fn+0x5e/0x26d [scsi_mod]
[<c019ee6a>] elv_insert+0x5a/0x134
[<c019efc1>] __elv_add_request+0x7d/0x82
[<c019f0ab>] elv_add_request+0x16/0x1d
[<e0e8d2ed>] pkt_generic_packet+0x107/0x133 [pktcdvd]
[<e0e8d772>] pkt_get_disc_info+0x42/0x7b [pktcdvd]
[<e0e8eae3>] pkt_open+0xbf/0xc56 [pktcdvd]
[<c0168078>] do_open+0x7e/0x246
[<c01683df>] blkdev_open+0x28/0x51
[<c014a057>] __dentry_open+0xb5/0x160
[<c014a183>] nameidata_to_filp+0x27/0x37
[<c014a1c6>] do_filp_open+0x33/0x3b
[<c014a211>] do_sys_open+0x43/0xc7
[<c014a2cd>] sys_open+0x1c/0x1e
[<c0102b82>] sysenter_past_esp+0x5f/0x85
プロセスがカーネルに入り、最終的にリフト()elv
アルゴリズムに関連するopen()を呼び出す方法に注意してください。