6.5K Views
October 13, 26
スライド概要
2026年4月18日(土)エセナおおた第1学習室Cにて
動画: https://www.youtube.com/watch?v=wIZpnaAK4Zo
プログラマー
jus共催 第74回Linuxのプロセススケジューラで遊ぶ シェル芸勉強会 11ヶ月ぶりです 上田 隆一 2026年4月18日 © 2026 上田隆一 第74回シェル芸勉強会
近況1: しぇるげいすきー(招待制シェル芸Misskeyサーバー) URL貼るのなんとなく解禁中 たぶん建設的な話ができそうなので 第74回シェル芸勉強会 2
近況2: Software Designの連載 「魅惑の自作シェルの世界」 まだ続いてます。終わらないような気がしてきた・・・ 4月号(41回): 変数RANDOM、SRANDOMとunset 5月号(42回): 特殊な変数(後編)+ time 6月号(43回): time(後編)と! 7月号(44回): ブレース付きのパラメータ展開(予定) その後の予定: 変数の置換、部分文字列の切り出し、 代替の文字列の指定、・・・ 第74回シェル芸勉強会 3
シェル芸とは マウスも使わず、ソースコードも残さず、GUIツールを立ち上げる間もなく、あらゆる 調査・計算・テキスト処理をCLI端末へのコマンド入力一撃で終わらすこと。あるいは そのときのコマンド入力のこと。 第74回シェル芸勉強会 4
今回の座学と問題 Linuxのタスクスケジューリング cronのほうじゃなくてnice値とかそっちのほう 内容 プロセス、タスクについて ちゅうい システム寄りの話題であんまり長いワンライナーは出てこないので、不満な 人は無理やりワンライナーでいろいろやってOSを破壊してください() うんちくはどんどん言ってください Linuxジャパンとは無関係です 第74回シェル芸勉強会 5
おさらい: プロセス メモリ上でユーザーのプログラムを管理する単位 例: Bashでコマンド(=プログラム) ps を立ち上げる ueda@p1gen3:~$ ps PID TTY TIME CMD 30166 pts/0 00:00:00 bash 30180 pts/0 00:00:00 ps #bashのプロセス #psのプロセス プロセスに対してLinux(カーネル)は 専用のアドレス空間を与える(論理アドレス空間、次のページ) 論理アドレス空間中で使う分だけメモリを割り当てる 第74回シェル芸勉強会 6
プロセスのメモリマップ cat /proc/$$/mmap で今使っているシェルのものを見てみましょう ueda@p1gen3:~$ cat /proc/$$/maps 59abce6c9000-59abce6f9000 r--p 00000000 103:02 45875758 59abce6f9000-59abce7e8000 r-xp 00030000 103:02 45875758 (略) 59abce82a000-59abce835000 rw-p 00000000 00:00 0 59abf9587000-59abf96d1000 rw-p 00000000 00:00 0 74ecdde00000-74ecdde28000 r--p 00000000 103:02 45900166 (略) 74ecde005000-74ecde012000 rw-p 00000000 00:00 0 74ecde053000-74ecde174000 r--p 00000000 103:02 45875280 (略) 74ecde1bc000-74ecde1be000 rw-p 00000000 00:00 0 74ecde1be000-74ecde1c2000 r--p 00000000 00:00 0 74ecde1c2000-74ecde1c4000 r--p 00000000 00:00 0 74ecde1c4000-74ecde1c6000 r-xp 00000000 00:00 0 74ecde1c6000-74ecde1c7000 r--p 00000000 103:02 45900161 (略) 7ffd1ec09000-7ffd1ec2a000 rw-p 00000000 00:00 0 ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 /usr/bin/bash /usr/bin/bash [heap] /usr/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/locale/locale-archive [vvar] [vvar_vclock] [vdso] /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 [stack] [vsyscall] stackやheapなどの区域分け コマンドや共有ライブラリのファイルがマップされている 第74回シェル芸勉強会実際に使われている物理メモリのアドレスは不明(隠蔽) 7
おさらい2: プロセスとスレッド プロセスの中には1つ以上のスレッドが存在 メインスレッドと、必要ならば他のスレッドを立ち上げることが可能 論理アドレス空間を共有 プロセスがフォークするとメインスレッドだけ残る 第74回シェル芸勉強会 8
メモリではプログラムの基本単位はプロセスだがCPUでは Linuxの場合、基本的にはスレッドが基本単位 伝統的なUnixではプロセスが単位なのでそういう意味では少し違う 講師の疑問: ほかのOSどうなってんだろ? このせいでいろいろ用語がねじれている (重箱の隅かもしれませんが)違いを突っついてみましょう 第74回シェル芸勉強会 9
名前のねじれ プロセスでないものに(表面上は)PIDがついている 問題1: プロセスでないものにPIDがついている例を抽出してみましょう マルチスレッドのプロセスがあるとPIDに欠番が出る 問題2: 2-1: マルチスレッドのプロセスの一覧を作る マルチスレッドのプロセスがなければ自分で作る 2-2: それらのスレッドの PID と「 LWP (light weight process)番号」を 出力する シェル芸やりたい人はPIDとLWPをいろいろ比較する 第74回シェル芸勉強会 10
問題1の解答例 カーネルスレッドにPIDがついているのを確認する例 ueda@p1gen6:~$ ps aux | grep USER PID %CPU %MEM root 2 0.0 0.0 root 3 0.0 0.0 root 4 0.0 0.0 ・・・ -e PID -Fe [ VSZ RSS TTY 0 0 ? 0 0 ? 0 0 ? STAT START S 12:21 S 12:21 I< 12:21 TIME COMMAND 0:00 [kthreadd] 0:00 [pool_workqueue_release] 0:00 [kworker/R-rcu_gp] カーネルスレッド: カーネルが作るスレッドでプロセスではない 第74回シェル芸勉強会 11
問題2-1の解答例 STATの列に l とあるとマルチスレッド化されている ueda@p1gen6:~$ ps aux | awk 'NR==1||$8~/l/' | awk 'NF=11' | column -t -c 11 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME systemd+ 544 0.0 0.0 91752 8244 ? Ssl 12:21 0:00 root 6676 0.0 0.0 153452 3388 ? Ssl 12:21 0:03 polkitd 6681 0.0 0.0 614400 12660 ? Ssl 12:21 0:01 root 6695 0.0 0.0 3106792 42660 ? Ssl 12:21 0:03 ・・・ COMMAND /usr/lib/systemd/systemd-timesyncd /usr/bin/nvidia-powerd /usr/lib/polkit-1/polkitd /snap/snapd/current/usr/lib/snapd/snapd 自分で作るときは sort に大きなファイルをソートさせるとよい ueda@p1gen6:~$ seq 100000000 > ~/a ueda@p1gen6:~$ sort a > /dev/null & sleep 5 ; ps u | awk '$8~/STAT|Rl/' [1] 25223 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND ueda 25223 502 1.1 2545452 754028 pts/1 Rl 16:22 0:25 sort a 他、 vim もマルチスレッド化されている模様。 sush もマルチスレッド化され ている。 第74回シェル芸勉強会 12
問題2-2の解答例 ps -L で LWP が出力可能 ueda@p1gen6:~$ ps aux | awk '$8~/l/{print $2}' | xargs ps -Lp PID LWP TTY STAT TIME COMMAND 544 544 ? Ssl 0:00 /usr/lib/systemd/systemd-timesyncd 544 560 ? Ssl 0:00 /usr/lib/systemd/systemd-timesyncd 6676 6676 ? Ssl 0:01 /usr/bin/nvidia-powerd 6676 6711 ? Ssl 0:00 /usr/bin/nvidia-powerd 6676 6712 ? Ssl 0:02 /usr/bin/nvidia-powerd ・・・ メインスレッドのLWPがPIDとして扱われる ということはPIDに欠番が出てるように見える 第74回シェル芸勉強会 13
どういうこと? Linuxは スレッドにTID(thread ID)というIDをつける スケジューリングはTID単位で行う メインスレッドのTIDをTGID(thread group ID)とする 名前のねじれ こういうこと psで表示される名前 Linuxでの名前 コメント(主観) PID TGID 視点の違い(メモリかCPUか) LWP TID なんだよlight weight processって 第74回シェル芸勉強会 14
Linuxのスケジューリング(基礎) カーネルスレッドやスレッドを「タスク」と呼ぶ task_struct 構造体で管理 タスクはたくさんあるのでCPUを使い回さないといけない タスクを「実行キュー」に入れて順番にCPUを使わせる 先頭のものを実行して・・・ 時間が来ると後ろにまわる システムコールでブロックが起こると寝る(待機状態) 実行キューは各CPUに 順番なんだけど優先度を設ける 第74回シェル芸勉強会 15
問題3: 次の操作をしてみましょう(ワンライナーでなくてもよいです) を2つ、同じCPUの上で立ち上げる nice値をいじってCPUをすごく不公平に使わせる 長いワンライナーを書きたい変態さんは、たくさん seq を立ち上げてnice値をひ とつ刻みで設定してみてください seq inf > /dev/null 第74回シェル芸勉強会 16
問題3の解答例(1/2) まず、特定のCPUにタスクを縛り付ける ueda@p1gen6:~$ taskset -c 0 seq inf > /dev/null & [1] 37873 ueda@p1gen6:~$ taskset -c 0 seq inf > /dev/null & [2] 37877 ueda@p1gen6:~$ top -bn 1 | grep -e PID -e seq PID USER PR NI VIRT RES SHR S %CPU 37873 ueda 20 0 15676 7564 6636 R 54.5 37877 ueda 20 0 15676 7636 6708 R 45.5 第74回シェル芸勉強会 %MEM 0.0 0.0 TIME+ COMMAND 1:29.56 seq 1:25.20 seq 17
問題3の解答例(2/2) nice値を変える( top の NI 、 PR 、 %CPU に注目) 優先度を低く ueda@p1gen6:~$ renice -n 19 -p 37873 37873 (process ID) 従来の優先順位は 0 で, 新しい優先順位は 19 です ueda@p1gen6:~$ top -bn 1 | grep -e PID -e seq PID USER PR NI VIRT RES SHR S %CPU %MEM 37877 ueda 20 0 15676 7636 6708 R 100.0 0.0 37873 ueda 39 19 15676 7564 6636 R 0.0 0.0 TIME+ COMMAND 2:22.98 seq 2:22.34 seq 優先度を高く( sudo が必要) ueda@p1gen6:~$ sudo renice -n -20 -p 37873 [sudo: authenticate] Password: 37873 (process ID) 従来の優先順位は 19 で, 新しい優先順位は -20 です ueda@p1gen6:~$ top -bn 1 | grep -e PID -e seq PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 37873 ueda 0 -20 15676 7564 6636 R 100.0 0.0 2:28.03 seq 37877 ueda 20 0 15676 7636 6708 R 0.0 0.0 3:26.52 seq 第74回シェル芸勉強会 18
本日の本題(もう結構時間たったけど): nice値を超えていく nice値で優先度最大のプロセスを黙らせることは可能か? 可能 知っておくこと スケジューリングクラスとスケジューリングポリシー 第74回シェル芸勉強会 19
Linuxのスケジューリングクラス 実は実行キューはCPU1個に対して複数設けることができる 「スケジューリングクラス」というものを 作って複数登録できるようになっている クラスは自身の実行キュー(キューとはかぎらない)を管理する 建前としてはカーネルから独立している クラス間には明確な優先度の差 原則、優先度の高いクラスが何か動かしたければ他は止まる 現行(6.6〜)のLinuxの実装(参考: 新Linuxカーネル解読室 ) stop, deadline, rt, fair, idleの5クラスが実装されている 6.12ではextというものも追加されたらしい(未調査) 第74回シェル芸勉強会 20
5つのクラス クラス なに? stop CPUの動的な着脱の際に使用するらしい(分からん) deadline ある周期で必ず1回処理したいときに使用 rt リアルタイムクラス(リアルタイム性は保証されない) fair 普通のクラス。いつも使ってる実行キューの持ち主 idle 暇なときに実行してよねというクラス 第74回シェル芸勉強会 21
Linuxのスケジューリングポリシー スケジューリングポリシー: 実行キューへのタスクの載せ方 ひとつのスケジューリングクラスに複数あってもよい 一覧(stopクラスを除く) クラス ポリシー(カッコ内: ps での略称) deadline SCHED_DEADLINE(DLN) rt SCHED_FIFO(FF)、SCHED_RR(RR) fair SCHED_NORMAL(TS)、SCHED_BATCH(B) idle SCHED_IDLE(IDL) SCHED_NORMAL: POSIXの呼び名だとSCHED_OTHERに相当 第74回シェル芸勉強会 22
各ポリシーの性質 ポリシー 性質 周期的に、設定した時刻まで必ず処理が完了するタイミング SCHED_DEADLINE でタスクの待機状態を解除(タスクのほうも、仕事が済んだ (DLN) ら待機状態になるループ処理でないといけない)参考資料 SCHED_FIFO(FF) 終わるまで待機状態以外のときはCPU独占 SCHED_RR(RR) FFと同じ実行キューにいるがタイムシェアリングする SCHED_NORMAL 普通のポリシーでタイムシェアリングする (TS) SCHED_BATCH(B) TSとほぼ同じだが若干優先度が下がる(らしい) SCHED_IDLE(IDL) 上のクラスの実行キューに何もないときだけ動く 第74回シェル芸勉強会 23
問題4: スケジューリングポリシーの観察 自身の環境で動いているタスクのスケジューリングポリシーが何種類あるか調べ てみましょう よかったらどんなタスクがどんなポリシーで動いているかも調査を 変態さん向け(危険) 重要そうなポリシーを変えてOSの調子が悪くなるか試してみてください 第74回シェル芸勉強会 24
問題4の解答例 講師の環境では3種類 ### ポリシーなのにコラム名がclsなのはPIDとTIDの話のときと同じ ### $ ps -eo cls | sed 1d | sort | uniq | wc -l 3 内訳 $ ps -eo cls | sed 1d | sort | uniq FF #SCHED_FIFO TS #SCHED_NORMAL IDL #SCHED_IDLE FFやIDLのタスクってどんなもの?(次ページ) 第74回シェル芸勉強会 25
FFやIDLのタスク システムレベルでは有効に活用されている カーネルスレッドの多くはSCHED_FIFO $ ps -eo cls,command | grep [F]F FF [migration/0] FF [idle_inject/0] FF [idle_inject/2] FF [migration/2] ・・・ IDLのものもある $ ps -eo cls,command | grep [I]DL IDL /usr/libexec/localsearch-3 #ファイル検索のインデックス作成プログラム 問題5: FF、TS、IDLのタスクを作り、互いの優先度の違いを確認してください 第74回シェル芸勉強会chrt コマンドを使います(優先度はFFの場合1、IDLの場合0で) 26
問題5の解答例(1/3) seq を3つ立ち上げてポリシーを変える $ for _ in $(seq 3) ; do taskset -c 0 seq inf > /dev/null & done [1] 40347 [2] 40348 [3] 40349 $ sudo chrt --pid -f 1 40347 $ sudo chrt --pid -i 0 40349 CPUの使用率を確認(FFの seq がCPUをほぼ独占) $ top -bn 1 | grep -e PID -e seq PID USER PR NI VIRT 40347 ueda -2 0 15676 40348 ueda 20 0 15676 40349 ueda 20 0 15676 続く 第74回シェル芸勉強会 RES 7476 7500 7556 SHR S %CPU 6548 R 100.0 6572 R 0.0 6628 R 0.0 %MEM 0.0 0.0 0.0 TIME+ COMMAND 0:29.70 seq 0:07.60 seq 0:06.76 seq 27
問題5の解答例(2/3) FFのプロセスを除去すると普通のプロセスがCPUをほぼ独占 $ kill 40347 [1] Terminated taskset -c 0 seq inf > /dev/null $ top -bn 1 | grep -e PID -e seq PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 40348 ueda 20 0 15676 7500 6572 R 100.0 0.0 0:22.45 seq 40349 ueda 20 0 15676 7556 6628 R 0.0 0.0 0:06.80 seq nice値を変えると? 第74回シェル芸勉強会 28
問題5の解答例(3/3) TSのnice値を-20(最高優先度に) ueda@x1gen13:~$ for _ in $(seq 2) ; do taskset -c 0 seq inf > /dev/null & done [1] 41271 [2] 41272 ueda@x1gen13:~$ sudo chrt --pid -f 1 41271 ueda@x1gen13:~$ sudo renice -n -20 -p 41272 41272 (process ID) 従来の優先順位は 0 で, 新しい優先順位は -20 です ueda@x1gen13:~$ top -bn 1 | grep -e PID -e seq (TIME+を見ているとそんなに状況は変わらない。ちゃんと統計とってないですが) 基本、FFのタスクが待機状態になったときにしか動かない 第74回シェル芸勉強会 29
補足: SCHED_FIFOのカーネルスレッド 優先度に違い ueda@p1gen3:~$ ps -eo cls,priority,pri,nice,rtprio,command CLS PRI PRI NI RTPRIO COMMAND ・・・ FF -100 139 99 [migration/0] FF -51 90 50 [idle_inject/0] TS 20 19 0 - [cpuhp/0] ・・・ FF -51 90 50 [irq/178-iwlwifi:default_queue] FF -51 90 50 [irq/179-iwlwifi:queue_1] ・・・ 優先度は高いけどだいたいのときはアイドル状態 ps aux で STAT の欄を確認のこと irq/... は割り込みの処理をスレッド化したもの リアルタイムカーネル化への取り組みの一環 第74回シェル芸勉強会 どこまでスレッド化するかをカーネルのコンパイル時に指定可能 30
補足 スロッティング rtクラスのタスクはデフォルトで5%だけCPUを空けるようになっている 暴走したときに操作不可能にならないように /proc/sys/kernel/sched_rt_period_us と /proc/sys/kernel/sched_rt_runtime_us で調整 SCHED_FIFOのタスクでCPUを全部使い、 sched_rt_runtime_us に -1 を設定すると完全に固まります(試しました) deadlineクラス ここを読むと設定方法わかります: https://b.ueda.tech/?post=20260404 第74回シェル芸勉強会 31
時間あまったときの問題 問題6: FF、RR、TS、B、IDLのタスクを1つずつワンライナーで作ってください 優先度の設定が面倒です 第74回シェル芸勉強会 32
まとめ プログラムの管理: メモリの視点からだとプロセス、CPUの視点からだとスレッド 用語のねじれがややこしい スケジューリングクラス、スケジューリングポリシーの勉強 Linuxの快適さに寄与していると個人的には思います カジュアルに使うと事故りそう 組み込みには便利そう 第74回シェル芸勉強会 33