103.6 レッスン 1
Certificate: |
LPIC-1 |
---|---|
Version: |
5.0 |
Topic: |
103 GNUおよびUnixコマンド |
Objective: |
103.6 プロセス実行の優先順位を変更する |
Lesson: |
1 of 1 |
はじめに
複数のプロセスを同時に実行できるOSを、マルチタスクOSないしマルチプロセッシングOSと呼びます。厳密には、複数のプロセスを同時に実行するには複数の処理装置(訳注:CPUなどの命令実行用のプロセッサ)が必要ですが、実行するプロセスを高速に切り替えることで、擬似的に同時実行をしているように見せることができます。処理装置よりもはるかに多くのプロセスを実行したいのが普通ですから、SMP(対称型マルチプロセッシング)など複数の処理装置を備えたシステムであっても、プロセスを高速に切り替える仕組みが採られています。
CPUが一度に処理できるのは一つのプロセスだけです。そして、プロセスの処理内容の大部分は、CPUを直接利用する演算などではなく、OSの機能を呼び出すシステムコールで行われます。システムコールでは主に、メモリの割り当て、ファイルシステムの読み書き、テキストの画面表示などのユーザーとの対話、ネットワーク転送など、デバイスとのやり取り(入出力)が行われます。現在のシステムでは、デバイスとのやり取りにはCPUの速度に比べて桁違いの長い時間がかかりますから、デバイスの応答を待っている間に別のプロセスにCPUを使用させると効率的です。そのため、マルチプロセッシングOSでは、システムコールが行われる度に実行するプロセスを選択しなおします(プロセススイッチと呼びます)。その際には、複数のキューを動的に使い分けることで、プロセスを効果的に管理しています。
しかしながら、システムコールの時にだけプロセス切り替え(プロセススイッチ)を行うのでは十分に効率的とは言えません。プロセスの中には、システムコールを行わずに長時間CPUを使い続けるものもあるからです。そのため現代的なOSでは、(タイマーによって)実行中のプロセスに割り込んで強制的にCPUの利用権を取り上げて、別のプロセスに切り替える仕組み(プリエンプション)を備えています。Linuxは、現代的なプリエンプティブ・マルチタスクOSの1つ、ということです。
Linuxのスケジューラー
Linuxはプリエンプティブ・マルチプロセッシングOSですから、プロセスのキューを管理するスケジューラーがあります。より正確に言うと、スケジューラーはプロセスから分岐した個々の スレッド も管理しますが、ここではプロセスもスレッドも同じだと考えても構いません。プロセスにはスケジューリングを調整する2つのパラメータがあります。ポリシー と 優先度 です。
ポリシーには2種類あります。リアルタイムポリシー と 通常ポリシー です。リアルタイムポリシーのプロセス同士では、そのまま優先度順にスケジューリングされます。より優先度の高いプロセスが実行可能になると、現在実行中のプロセスはプリエンプトされ、CPUはより優先度の高いプロセスの処理をします。より優先度の高いプロセスがアイドル状態になるかハードウェア(デバイス)の応答待ちになるまで、優先度の低いプロセスは処理されません。
リアルタイムポリシーのプロセスは通常ポリシーのプロセスよりも優先的に処理されます。Linuxは汎用OSであり、リアルタイムポリシーのプロセスはわずかしかありません。システムのプログラムもユーザーのプログラムも、大部分は通常ポリシーのプロセスです。通常ポリシーのプロセスはたいてい同じ優先度ですが、その中での優先順位を nice値 で定めることができます。通常ポリシーのプロセス同士で優先順位を定めるnice値のことを動的優先度と呼び、全プロセスの優先順位を決める優先度(静的 優先度)と区別します。
Linuxのスケジューラーには様々な設定があり、優先順位を決める複雑な方法も存在しますが、ポリシーと優先度という2つの概念はどの方法にも当てはまります。プロセスのスケジューリングを詳しく調べて調整する際には、通常ポリシーのプロセスの優先度を調整しているのだということを忘れないようにしてください。
優先順位を知る
Linuxでは、リアルタイムポリシーのプロセスに0から99の数値で静的優先度が割り振られ、通常ポリシーのプロセスには100から139の数値で静的優先度が割り振られます。通常ポリシーのプロセスの優先度には40段階あるということです。値が低いほど優先度が高くなります。 /proc
ファイルシステム内でプロセスごとに作成される sched
ファイルに静的優先度が書かれています。
$ grep ^prio /proc/1/sched prio : 120
prio
で始まる行に静的優先度が書かれています(上の例で見ているPIDが1のプロセスは、カーネルがシステムの初期化の際に開始する最初のプロセスである init ないし systemd です)。通常ポリシーのプロセスの優先度は標準で120です。この値を100から139の間で増減できます。ps -Al
か ps -el
のコマンドで全ての実行中のプロセスの優先度を確かめられます。
$ ps -el F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 1 0 0 80 0 - 9292 - ? 00:00:00 systemd 4 S 0 19 1 0 80 0 - 8817 - ? 00:00:00 systemd-journal 4 S 104 61 1 0 80 0 - 64097 - ? 00:00:00 rsyslogd 4 S 0 63 1 0 80 0 - 7244 - ? 00:00:00 cron 1 S 0 126 1 0 80 0 - 4031 - ? 00:00:00 dhclient 4 S 0 154 1 0 80 0 - 3937 - pts/0 00:00:00 agetty 4 S 0 155 1 0 80 0 - 3937 - pts/1 00:00:00 agetty 4 S 0 156 1 0 80 0 - 3937 - pts/2 00:00:00 agetty 4 S 0 157 1 0 80 0 - 3937 - pts/3 00:00:00 agetty 4 S 0 158 1 0 80 0 - 3937 - console 00:00:00 agetty 4 S 0 160 1 0 80 0 - 16377 - ? 00:00:00 sshd 4 S 0 280 0 0 80 0 - 5301 - ? 00:00:00 bash 0 R 0 392 280 0 80 0 - 7221 - ? 00:00:00 ps
PRI
列から静的優先度がわかります。先ほどの例で見た値(120)と違う値が表示されていることに注意してください。歴史的な理由から、ps
で表示される優先度はデフォルトでは-40から99です。実際の優先度を求めるには40を足します(上の例では80 + 40 = 120になります)。
top
コマンドを実行すると、Linuxカーネルに管理されているプロセスのリアルタイムの状態を動的に監視できます。top
の優先度の値の表示は、これまた優先度そのものではありません。リアルタイムポリシーのプロセスと通常ポリシーのプロセスを識別しやすくするために、top
では100を引いた優先度が表示されます。これにより、リアルタイムポリシーのプロセスは負の値になります(リアルタイムを意味する rt と表示されることもあります)。通常ポリシーのプロセスは0から39になります。
Note
|
いろいろなオプションを指定して $ ps -e -o user,uid,comm,tty,pid,ppid,pri,pmem,pcpu --sort=-pcpu | head |
プロセスのnice値
通常ポリシーのプロセスは、デフォルトではnice値が0(優先度は120)で開始されます。niceなプロセスは実行待ちキューで他のプロセスに優先順位を譲るという発想から nice という名前が付けられました。nice値は-20(niceなプロセスではなく優先度が高い)から19(niceなプロセスで優先度が低い)までの範囲です。Linuxでは同じプロセスから分岐した各スレッドに異なるnice値を割り当てることもできます。ps
の NI
列に nice 値が示されます。
プロセスのnice値を減らす(優先度を上げる)ことができるのはrootユーザーだけです。nice
コマンドで標準とは異なる優先度(0とは異なるnice値)でプロセスを開始できます。nice
コマンドをデフォルトで使うとnice値が10になり、-n
オプションに続けて値を指定するとnice値が指定した値になります。
$ nice -n 15 tar czf home_backup.tar.gz /home
このようにすると、tar
コマンドはnice値15で実行されます。renice
コマンドで実行中のプロセスの優先度(nice値)を変更できます。-p
オプションに続けてPIDを指定します(nice値を減らすことができるのはrootユーザーだけだということに注意してください)。
# renice -10 -p 2164 2164 (process ID) old priority 0, new priority -10
-g
オプションに続けてPGID(プロセスグループID)を指定するとそのPGIDのプロセス全部の優先度(nice値)を一括して変更でき、-u
オプションに続けてユーザー名を指定するとそのユーザーが開始したプロセス全部の優先度(nice値)を一括して変更できます。renice +5 -u users
を実行すると、users という名前のユーザーが開始したプロセスのnice値が5増えます。
renice
コマンド以外でも top
コマンドでプロセスの優先度(nice値)を変えられます。top
の出力が表示されている画面で r
を押してからPIDを入力してエンターキーを押し、nice値を入力してエンターキーを押すとその値に変えられます(訳注:プロセスのnice値を減らす(優先度を上げる)ことができるのはrootユーザーだけです)。
top - 11:55:21 up 23:38, 1 user, load average: 0,10, 0,04, 0,05 Tasks: 20 total, 1 running, 19 sleeping, 0 stopped, 0 zombie %Cpu(s): 0,5 us, 0,3 sy, 0,0 ni, 99,0 id, 0,0 wa, 0,2 hi, 0,0 si, 0,0 st KiB Mem : 4035808 total, 774700 free, 1612600 used, 1648508 buff/cache KiB Swap: 7999828 total, 7738780 free, 261048 used. 2006688 avail Mem PID to renice [default pid = 1] PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 74232 7904 6416 S 0,000 0,196 0:00.12 systemd 15 root 20 0 67436 6144 5568 S 0,000 0,152 0:00.03 systemd-journal 21 root 20 0 61552 5628 5000 S 0,000 0,139 0:00.01 systemd-logind 22 message+ 20 0 43540 4072 3620 S 0,000 0,101 0:00.03 dbus-daemon 23 root 20 0 45652 6204 4992 S 0,000 0,154 0:00.06 wickedd-dhcp4 24 root 20 0 45648 6276 5068 S 0,000 0,156 0:00.06 wickedd-auto4 25 root 20 0 45648 6272 5060 S 0,000 0,155 0:00.06 wickedd-dhcp6
PID to renice [default pid = 1]
というメッセージに示されているように、PIDを入力せずにエンターキーを押すと、最初の行に表示されているプロセスのPIDがデフォルトで選ばれます。そのプロセスとは別のプロセスを選ぶ場合はPIDを入力してエンターキーを押してください。Renice PID 1 to value
のようなメッセージが表示されるので、変更後のnice値を入力してエンターキーを押すとその値に変更できます。
演習
-
プリエンプティブ・マルチタスクOSでは、CPUがあるプロセスの処理をしているときにもっと優先度の高いプロセスが実行キューに入るとどうなりますか?
-
以下の
top
の画面表示を見て問いに答えてください。top - 08:43:14 up 23 days, 12:29, 5 users, load average: 0,13, 0,18, 0,21 Tasks: 240 total, 2 running, 238 sleeping, 0 stopped, 0 zombie %Cpu(s): 1,4 us, 0,4 sy, 0,0 ni, 98,1 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st MiB Mem : 7726,4 total, 590,9 free, 1600,8 used, 5534,7 buff/cache MiB Swap: 30517,0 total, 30462,5 free, 54,5 used. 5769,4 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 171420 10668 7612 S 0,0 0,1 9:59.15 systemd 2 root 20 0 0 0 0 S 0,0 0,0 0:02.76 kthreadd 3 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_par_gp 8 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 mm_percpu_wq 9 root 20 0 0 0 0 S 0,0 0,0 0:49.06 ksoftirqd/0 10 root 20 0 0 0 0 I 0,0 0,0 18:24.20 rcu_sched 11 root 20 0 0 0 0 I 0,0 0,0 0:00.00 rcu_bh 12 root rt 0 0 0 0 S 0,0 0,0 0:08.17 migration/0 14 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/0 15 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/1 16 root rt 0 0 0 0 S 0,0 0,0 0:11.79 migration/1 17 root 20 0 0 0 0 S 0,0 0,0 0:26.01 ksoftirqd/1
リアルタイムポリシーのプロセスはどれですか。PIDを答えてください。
-
以下の
ps-el
の画面表示を見て問いに答えてください。F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 1 0 0 80 0 - 42855 - ? 00:09:59 systemd 1 S 0 2 0 0 80 0 - 0 - ? 00:00:02 kthreadd 1 I 0 3 2 0 60 -20 - 0 - ? 00:00:00 rcu_gp 1 S 0 9 2 0 80 0 - 0 - ? 00:00:49 ksoftirqd/0 1 I 0 10 2 0 80 0 - 0 - ? 00:18:26 rcu_sched 1 I 0 11 2 0 80 0 - 0 - ? 00:00:00 rcu_bh 1 S 0 12 2 0 -40 - - 0 - ? 00:00:08 migration/0 1 S 0 14 2 0 80 0 - 0 - ? 00:00:00 cpuhp/0 5 S 0 15 2 0 80 0 - 0 - ? 00:00:00 cpuhp/1
優先度が最も高いプロセスはどれですか。PIDを答えてください。
-
renice
コマンドでプロセスのnice値を変更しようとしたところ、以下のエラーメッセージが表示されました。$ renice -10 21704 renice: failed to set priority for 21704 (process ID): Permission denied
このエラーの原因は何でしょう?
発展演習
-
プロセスの優先度を変更する必要を感じるのは、たいてい、あるプロセスがあまりにも多くのCPU時間を占有しているときです。そこで、
ps
コマンドにオプションを指定してすべてのシステムプロセスの詳細表示を見てみましょう。CPU使用率の昇順でソートするにはどのような--sort
オプションを指定しますか? -
schedtool
は、CPUスケジューリングに関するあらゆるパラメータを設定・表示できるコマンドです。(top
やps
の表示から適当にPIDを選んで)指定したプロセスのスケジューリングパラメータを表示してください。また、そのプロセスの優先度を-90(top
の表示によるもの)に設定してリアルタイムポリシーに変更してください。
まとめ
このレッスンでは、Linuxが管理しているプロセスの間でCPU時間をどのように割り当てているかを説明しました。システムがベストのパフォーマンスを発揮するには、重要なプロセスがそれほど重要でないプロセスよりも優先的に処理されるべきです。以下の順で説明しました。
-
マルチプロセッシングOSの基本概念。
-
プロセススケジューラーとスケジューリングの実施方法。
-
Linuxでの優先度とnice値。
-
Linuxでのプロセス優先度の解釈。
-
実行前及び実行中におけるプロセス優先度の変更方法。
演習の解答
-
プリエンプティブ・マルチタスクOSでは、CPUがあるプロセスの処理をしているときにもっと優先度の高いプロセスが実行キューに入るとどうなりますか?
そのプロセスの処理を中断し、代わりに優先度の高いプロセスの実行処理をします。
-
以下の
top
の画面表示を見て問いに答えてください。top - 08:43:14 up 23 days, 12:29, 5 users, load average: 0,13, 0,18, 0,21 Tasks: 240 total, 2 running, 238 sleeping, 0 stopped, 0 zombie %Cpu(s): 1,4 us, 0,4 sy, 0,0 ni, 98,1 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st MiB Mem : 7726,4 total, 590,9 free, 1600,8 used, 5534,7 buff/cache MiB Swap: 30517,0 total, 30462,5 free, 54,5 used. 5769,4 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1 root 20 0 171420 10668 7612 S 0,0 0,1 9:59.15 systemd 2 root 20 0 0 0 0 S 0,0 0,0 0:02.76 kthreadd 3 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_gp 4 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_par_gp 8 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 mm_percpu_wq 9 root 20 0 0 0 0 S 0,0 0,0 0:49.06 ksoftirqd/0 10 root 20 0 0 0 0 I 0,0 0,0 18:24.20 rcu_sched 11 root 20 0 0 0 0 I 0,0 0,0 0:00.00 rcu_bh 12 root rt 0 0 0 0 S 0,0 0,0 0:08.17 migration/0 14 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/0 15 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/1 16 root rt 0 0 0 0 S 0,0 0,0 0:11.79 migration/1 17 root 20 0 0 0 0 S 0,0 0,0 0:26.01 ksoftirqd/1
リアルタイムポリシーのプロセスはどれですか。PIDを答えてください。
PID12と16。
-
以下の
ps-el
の画面表示を見て問いに答えてください。F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 1 0 0 80 0 - 42855 - ? 00:09:59 systemd 1 S 0 2 0 0 80 0 - 0 - ? 00:00:02 kthreadd 1 I 0 3 2 0 60 -20 - 0 - ? 00:00:00 rcu_gp 1 S 0 9 2 0 80 0 - 0 - ? 00:00:49 ksoftirqd/0 1 I 0 10 2 0 80 0 - 0 - ? 00:18:26 rcu_sched 1 I 0 11 2 0 80 0 - 0 - ? 00:00:00 rcu_bh 1 S 0 12 2 0 -40 - - 0 - ? 00:00:08 migration/0 1 S 0 14 2 0 80 0 - 0 - ? 00:00:00 cpuhp/0 5 S 0 15 2 0 80 0 - 0 - ? 00:00:00 cpuhp/1
優先度が最も高いプロセスはどれですか。PIDを答えてください。
PID12。
-
renice
コマンドでプロセスのnice値を変更しようとしたところ、以下のエラーメッセージが表示されました。$ renice -10 21704 renice: failed to set priority for 21704 (process ID): Permission denied
このエラーの原因は何でしょう?
nice値を減らすことができるのはrootユーザーだけなのに、一般ユーザーがnice値を減らそうとしたこと。
発展演習の解答
-
プロセスの優先度を変更する必要を感じるのは、たいてい、あるプロセスがあまりにも多くのCPU時間を占有しているときです。そこで、
ps
コマンドにオプションを指定してすべてのシステムプロセスの詳細表示を見てみましょう。CPU使用率の昇順でソートするにはどのような--sort
オプションを指定しますか?$ ps -el --sort=pcpu
-
schedtool
は、CPUスケジューリングに関するあらゆるパラメータを設定・表示できるコマンドです。(top
やps
の表示から適当にPIDを選んで)指定したプロセスのスケジューリングパラメータを表示してください。また、そのプロセスの優先度を-90(top
の表示によるもの)に設定してリアルタイムポリシーに変更してください。$ schedtool 1750
$ schedtool -R -p 89 1750