前回は,
今回の実行例は,cgroup_
と指定して,
そして,root
ユーザで実行しています。
スレッド化サブツリーの操作
それでは早速,
スレッド化サブツリーを作るには2つの方法があります。
cgroup.typeファイルへの書き込み
まずは1つめの方法です。
シンプルにcgroup.
ファイルにthreaded
という文字列を書き込むだけです。これまで説明してきたcgroupの操作方法をご存知であれば想像がつく方法かと思います。
この結果次のようになります。
threaded
という文字列を書き込んだcgroupのタイプは"threaded"になるthreaded
という文字列を書き込んだcgroupの親cgroupは"domain threaded"になるthreaded
という文字列を書き込んだcgroupの親cgroup配下の"threaded"以外のcgroupは"domain invalid"になる
つまり,threaded
と書き込んだcgroupの親cgroup配下が,
できあがったスレッド化サブツリー内の"domain invalid"な状態のcgroupすべてにthreaded
という文字列を書き込んでいかないと,
この動きを確認してみましょう。
cgroup v2のroot配下にtd
というディレクトリを,td
配下にth01
,th02
というcgroupを2つ作成します。
# mount -t cgroup2 cgroup2 /sys/fs/cgroup/ (cgroup v2のマウント) # mkdir -p td/th{01,02} (tdとその配下にth01,th02というcgroupを作成) # tree -d /sys/fs/cgroup/ /sys/fs/cgroup/ └── td ├── th01 └── th02 3 directories
作成した3つのcgroup内のプロセスとコントローラファイルの中身を確認します。
# cat td/cgroup.procs
# cat td/cgroup.controllers
# cat td/th0{1,2}/cgroup.procs
# cat td/th0{1,2}/cgroup.controllers
(作成直後なのでプロセスもコントローラも表示されない)
まだ作っただけでプロセスの登録もコントローラの登録も行っていませんので,
それぞれのcgroup.
ファイルも確認しておきましょう。
# find /sys/fs/cgroup -name "cgroup.type" -exec cat {} \;
domain
domain
domain
(作成したいずれのcgroupのタイプもdomain)
いずれのcgroupも初期状態ですのですべて"domain"となっています
この状態でth01
を"threaded"としてみましょう。
# echo "threaded" > /sys/fs/cgroup/td/th01/cgroup.type (th01をthreadedに変更) # cat /sys/fs/cgroup/td/th01/cgroup.type threaded (threadedに変更されている)
threaded
になりましたね。他のcgroupがどうなっているのかも見てみましょう。
# cat /sys/fs/cgroup/td/cgroup.type domain threaded (th01の親cgroupはdomain threadedに変化している) # cat /sys/fs/cgroup/td/th02/cgroup.type domain invalid (td配下のcgroupはdomain invalidに変化している)
"threaded"であるth01
の親cgroupであるtd
はスレッド化サブツリーのrootである"domain threaded"に,th02
は"domain invalid"となりました。
つまり"threaded cgroup"の親は"domain threaded"に,
このままではth02
は使えない状態のままです。th02
を機能させるためには"threaded"にする必要があります。
# echo "threaded" > /sys/fs/cgroup/td/th02/cgroup.type # cat /sys/fs/cgroup/td/th02/cgroup.type threaded
これでth02
がthreadedになり,
スレッド化サブツリー内へのタスクの追加
2つめの方法を見る前に,
スレッド化サブツリーにマルチスレッドプロセスを登録させるには,cgroup.
に登録する必要があります。"threaded"や"domain threaded"のcgroupであっても,cgroup.
にプロセスやスレッドのIDは登録できません。
まずはマルチスレッドプロセスを起動してみます。次のように2つのスレッドを持つプロセスですpstree
コマンドではスレッドは中かっこ{}
で囲われます)。
# pstree -p 907 threadtest(907)─┬─{threadtest}(908) └─{threadtest}(909)
このマルチスレッドプロセスの親となるプロセスのPID907
を図3で作ったcgroup td
に登録してみます。
# echo 907 > /sys/fs/cgroup/td/cgroup.procs (PPIDをdomain threadedのcgroup.procsに登録) # cat /sys/fs/cgroup/td/cgroup.procs 907 (cgroup.procsにはプロセスのIDとなるPPIDのみ登録されている) # cat /sys/fs/cgroup/td/cgroup.threads 907 908 909 (cgroup.threadsには同じプロセスに属するスレッドも含めて登録されている)
PPIDの907
をcgroup.
に登録すると,cgroup.
にはそのPIDが登録され,cgroup.
にはその子となるスレッドのID908
,909
が登録されています。
cgroup.
への登録は"domain threaded'であるcgroupへの登録である必要はなく,th01
やth02
への登録でも構いません。次の操作は"threaded"であるth01
へマルチスレッドプロセスを登録している例です。
# echo 907 > /sys/fs/cgroup/cgroup.procs (前の例の後に実行するために一度プロセスをrootに戻す) # echo 907 > /sys/fs/cgroup/td/th01/cgroup.procs (threadedであるth01へマルチスレッドプロセスを登録) # cat /sys/fs/cgroup/td/th01/cgroup.threads 907 908 909 (cgroup.threadsには同じプロセスに属するスレッドも含めて登録されている)
上の例で,cgroup.
の内容を見ています。これは"threaded"なcgroupのcgroup.
ファイルは読み取りできないからです。cgroup.
を読もうとすると次のようにエラーになります。
"domain threaded"であるcgroupのcgroup.
は先の例で実行したように読み取れます。
# cat /sys/fs/cgroup/td/th01/cgroup.procs cat: /sys/fs/cgroup/td/th01/cgroup.procs: Operation not supported
この例ではマルチスレッドプロセスのPPIDを登録しました。代わりにスレッドのIDをcgroup.
に登録しても同じ結果となります。上の例のマルチスレッドプロセス内のスレッドのTIDである909
をcgroup.
に登録してみましょう。
# echo 909 > /sys/fs/cgroup/td/cgroup.procs (マルチスレッド内のスレッドのIDをcgroup.procsに登録) # cat /sys/fs/cgroup/td/cgroup.procs 907 (cgroup.procsにはPPIDが登録されている) # cat /sys/fs/cgroup/td/cgroup.threads 907 908 909 (cgroup.threadsにはマルチスレッドプロセスのPIDとTIDが登録されている)
このように,cgroup.
ではPPIDが表示され,cgroup.
に表示されていることがわかります。
先にcgroup.
に登録する必要があります」
cgroup.
ではなく,cgroup.
に登録を試みます。先の例に続けて実行する場合は,
# echo 907 > /sys/fs/cgroup/cgroup.procs (前の例の後に実行するために一度プロセスをrootに戻す) # echo 907 > /sys/fs/cgroup/td/cgroup.threads bash: echo: write error: Operation not supported # echo 907 > /sys/fs/cgroup/td/th01/cgroup.threads bash: echo: write error: Operation not supported (エラーになる)
このようにいきなりcgroup.
に登録しようとするとエラーとなります。
一度マルチスレッドプロセスをスレッド化サブツリーに登録したあとは,
# echo 907 > /sys/fs/cgroup/td/cgroup.procs (マルチスレッドプロセスをdomain threadedに登録) # cat /sys/fs/cgroup/td/cgroup.procs 907 (PPIDが登録された) # cat /sys/fs/cgroup/td/cgroup.threads 907 908 909 (PPIDとTIDが登録されている) # echo 908 > /sys/fs/cgroup/td/th01/cgroup.threads (スレッドをth01に移動) # cat /sys/fs/cgroup/td/th01/cgroup.threads 908 (移動された) # echo 909 > /sys/fs/cgroup/td/th02/cgroup.threads (別のスレッドをth02に移動) # cat /sys/fs/cgroup/td/th02/cgroup.threads 909 (移動された)
ここでスレッドcgroup.
でなくcgroup.
に登録すると,
# echo 909 > /sys/fs/cgroup/td/th01/cgroup.procs (プロセス内のTIDをth01のcgroup.procsに登録) # cat /sys/fs/cgroup/td/th01/cgroup.threads 908 907 909 (登録したスレッドだけでなく属するプロセス全体が移動した)
色々試して頭が混乱したかもしれませんね。ここまでに試したことをまとめておきましょう。
- マルチスレッドプロセスをスレッド化サブツリーに移動する場合は,
まずはスレッド化サブツリー内のcgroupの cgroup.
に登録する必要があるprocs - 登録するIDはプロセス内のTIDでも良い
- "threaded"なcgroupの
cgroup.
は読み取れない。登録されているIDを確認するにはprocs cgroup.
を読む必要があるthreads domain threaded
なcgroupのcgroup.
は読み取れるprocs
- TIDであっても
cgroup.
への書き込みではマルチスレッドプロセス全体が移動するprocs