Linuxは(まだ)POSIX.1標準に準拠していません 言います プロセスのrenice
は「プロセス内のすべてのシステムスコープスレッド」に影響を与えると pthreads(7)doc 「スレッドは共通のナイス値を共有しない」。
ただし、特定のプロセスに関連するrenice
"すべて"が便利な場合があります(1つの例は、Apacheの子プロセスとそのすべてのスレッドです)。そう、
renice
allthreadsはどうすればよいですか?renice
できますか?かなり簡単な解決策を探しています。
プロセスグループ が役立つ場合があることはわかっていますが、それらは必ずしも私がやりたいことと一致するとは限りません。より広いまたは異なるプロセスのセットを含めることができます。
cgroup
が管理するsystemd
を使用することも役立つ場合がありますが、それについて知りたいと思っていても、ほとんどの場合「標準」の解決策を探しています。
編集:また、man (7) pthreads
は、「プロセス内のすべてのスレッドは同じスレッドグループに配置されます。スレッドグループのすべてのメンバーは同じPIDを共有します」と言います。それで、それ自身のPIDを持たないものをrenice
することも可能ですか?
systemdを使用する場合は特に、自動タスクのグループ化のため、Nice値は「システム全体」ではそれほど関連性がない可能性があることに注意してください。詳細については この回答 を参照してください。
Linuxに関する重要な質問です。ドキュメントには疑問が残るためです(たとえば、独自のPIDを持たないスレッドについて)。
注: この答え はLinuxスレッドを正確に説明します。
要するに、カーネルは「実行可能なエンティティ」、つまりrunおよびscheduledが可能なもののみを処理します。カーネルに関しては、これらのエンティティはプロセスと呼ばれます。スレッドは、(少なくとも)メモリ空間とシグナルハンドラを別のスレッドと共有する一種のプロセスです。
このようなすべてのプロセスには、システム全体で一意の識別子であるPID(プロセスID)があります。いわゆるスレッドの場合、TID(スレッドID)と呼ばれることもありますが、sysadmin(およびカーネル!)の観点からは、TIDとPIDは同じものです(同じ名前空間を共有します)。
その結果、canrenice
それぞれの「スレッド」には、ownPID1。
renice
へのすべてのPIDを再帰的に検索するすてきなプロセスの子孫(子またはスレッドグループ内)であるすべてのプロセス(「通常」または「スレッド」)のPIDを取得する必要があります。これは再帰的であるべきです(子供たちの子供を考えると)。
Anton Leontievの答えはそのためのヒントを与えます:/proc/$PID/task/
のすべてのフォルダー名は、潜在的な子プロセスをリストするchildren
ファイルを含むスレッドのPIDです。
ただし、これには再帰性がないため、これらを見つけるためのすばやく汚れたシェルスクリプトを次に示します。
#!/bin/sh
[ "$#" -eq 1 -a -d "/proc/$1/task" ] || exit 1
PID_LIST=
findpids() {
for pid in /proc/$1/task/* ; do
pid="$(basename "$pid")"
PID_LIST="$PID_LIST$pid "
for cpid in $(cat /proc/$1/task/$pid/children) ; do
findpids $cpid
done
done
}
findpids $1
echo $PID_LIST
プロセスPID 1234を再帰的に実行したい場合は、次のようにします。
renice -n 15 -p $(/path/to/findchildren.sh 1234)
1 POSIXに準拠するために、スレッド内でgetpid(2)
を呼び出すと、この実行可能エンティティのシステム全体で一意のID(PID)がないので、 「スレッドグループ」内のメインプロセスのPID。代わりにgettid(2)
を呼び出す必要があります。詳細は this answer を参照してください。
/proc/$PID/task
を使用して、特定のプロセスのすべてのスレッドを検索できるため、次のように使用できます
$ ls /proc/$PID/task | xargs renice $PRIO
to renice
all threads指定されたプロセスに属しています。
同じように/proc/$PID/task/$PID/children
を使用して、すべての子プロセスを検索できます(または/proc/$PID/task/*/children
が必要な場合は、すべての子プロセスを検索しますthreads特定のプロセスの)。
$ cat /proc/$PID/task/$PID/children | xargs renice $PRIO
$ cat /proc/$PID/task/*/children | xargs renice $PRIO
プロセスのPIDとスレッドIDをTIDまたはpsコマンドのLPWに書き込むことはありません。 s
コマンドにはスレッドを表示するオプションがあり、top
またはhtop
の下で、スレッドを切り替えてH
文字で処理します。以前に@Totorによって伝えられたように、カーネル> 2.6の現在の実装であるNPTLでは、すべてのスレッドが同じpidを持っていますが、異なるtidを持っています。次の方法で、プロセスのすべてのスレッドを表示します。
$ ps -Ljf <pid>
これらのtidは/proc/<pid>/task
の下のディレクトリの名前であり、renice(1)が適用されたときにデフォルトの引数がpidであると言ってもpidに対しては、メインスレッドのみを放棄します(これは、setpriority(2)で記述されているLinux実装のバグです)。 tidとスレッドをレニシングします。 @Antonの答えが有効であるのはそのためです。
しかし、たいていの場合、望ましい結果を得る簡単な方法があります。これらすべてのスレッドは、グループリーダーのPIDである同じpgidを共有します。以下を発行することにより、pgidで再取得できます。
$ renice -g <pgid>
同じグループリーダーに依存する他のプロセスを再利用したくない場合は、@ Antonのレシピを使用する必要があります。
$ renice <priority> $(ls -1 /proc/<pid>/task)
または:
$renice <priority> $(ps --no-header -Lo tid <pid>)
また、同じグループの他のプロセスとして、やり直したいプロセス、つまり同じpgidを共有するプロセスを知りたい場合もあります。 ps(1)を使用できます。ps
ではグループリーダーによるプロセスの選択は許可されていませんが、ps
を実行します。 pgid 1908
のプロセスは、次のコマンドで表示されます。
$ ps --no-header axo pid,pgid |sed -n '/^ *[0-9][0-9]* *1908/s/[0-9][0-9]* *$//p'
またはawkでsedを使用する場合:
$ ps --no-header axo pid,pgid|awk '{if ($2=="1908") print $1;}'
man renice
によると(私の強調):
renice
は、1つ以上の実行中のプロセスのスケジューリング優先順位を変更します。最初の引数は、使用する優先度の値です。 他の引数は、プロセスID(デフォルト)、プロセスグループID、ユーザーID、またはユーザー名として解釈されます。 (...)
そして実際、 man pgrep
は例として示しています:
例4:すべてのchromeプロセスをより適切に実行する:
$ renice +4 $(pgrep chrome)
これらによれば、renice
とpgrep
の-w | --lightweight
スイッチを組み合わせて、すべてのスレッドを再許可することができます。 、 そのようです:
renice <priority> $(pgrep -w <process_name>)
そして再表示するすべての子プロセス:
renice <priority> $(pgrep -P $(pgrep <process_name>))
また、-f
スイッチをpgrep
と共に使用して、プロセス名だけでなくコマンドライン全体を照会することもできます(完全一致である必要はありません)。
Reniceを使用するときは、-p(プロセスID)ではなく-g(プロセスグループ)引数を使用することをお勧めします。 bash-fooがなくても同じことができます。
つまり.
(Sudo) renice -n <NEW_PRIORITY> -g <MAIN_PROCESS_ID>