Linux上の1つのプロセスのすべてのスレッド(および子)を放棄する方法は?


22

Linuxは(まだ)POSIX.1標準に従っていないと言うことreniceに従っているため、プロセス上は、「プロセス内のすべてのシステム・スコープ・スレッド」に影響をpthreadsの(7)DOC「のスレッドが共通の素敵な値を共有しません」。

ただし、renice特定のプロセスに関連する「すべて」が便利な場合もあります(1つの例は、Apacheの子プロセスとそのすべてのスレッドです)。そう、

  • 特定のプロセスに属するreniceすべてのスレッドをどのようにすればよいですか?
  • 特定のプロセスに属するreniceすべての子プロセスはどうすればよいですか?

私はかなり簡単な解決策を探しています。

私はことを知っているプロセスグループは、時には役に立つことができ、しかし、彼らはいつも私が何をしたいのか一致しません:彼らはプロセスのより広範または異なるセットを含めることができます。

cgroupマネージドを使用することsystemdも役立つかもしれませんが、それについて聞いてみたいと思っても、ほとんどの場合「標準」ソリューションを探しています。

編集:また、man (7) pthreads「プロセス内のすべてのスレッドは同じスレッドグループに配置されます。スレッドグループのすべてのメンバーは同じPIDを共有します」。それで、それreniceがそれ自身のPIDを持っていない何かにさえ可能ですか?

回答:


19

あなたは使用することができます/proc/$PID/taskので、あなたが使用することができ、与えられたプロセスのすべてのスレッドを見つけるために、

$ ls /proc/$PID/task | xargs renice $PRIO

reniceすべてのスレッドを与えられたプロセスに属します。

同じ方法/proc/$PID/task/$PID/childrenを使用して、すべての子プロセスを見つけることができます(または、特定のプロセスのすべてのスレッドの/proc/$PID/task/*/childrenすべての子プロセスが必要な場合)。

$ cat /proc/$PID/task/$PID/children | xargs renice $PRIO
$ cat /proc/$PID/task/*/children | xargs renice $PRIO

man (7) pthreads現在の(NPTL)実装について:「プロセス内のすべてのスレッドは同じスレッドグループに配置されます。スレッドグループのすべてのメンバーは同じPIDを共有します」および「スレッドは共通のnice値を共有しません」。それでは、renicePIDを使用して独自のPIDを持たないスレッドをどのように変更できますか?
トーター

スレッドIDでreniceを試してみましたが、報告され24995 (process ID) old priority 0, new priority -10ます。24995はに表示されないpsため、プロセスではありません。多分、スレッドの解放は実際に機能するのでしょうか?
ステファンライク

9

すてきな値またはCPUシェア?

systemdを使用する場合は特に、自動タスクグルーピングにより、最近ではnice値はそれほど「システム全体」に関連しない場合があることに注意してください。詳細については、この回答をご覧ください。

スレッドとプロセスの違い

Linuxでの重要な質問。ドキュメントは疑念を永続化します(たとえば、スレッドが独自のPIDを持たないことについて)。

注:この回答は、Linuxスレッドを正確に説明しています。

要するに、カーネルは「実行可能なエンティティ」、つまり実行およびスケジュール可能なもののみを処理します。カーネルに関しては、これらのエンティティはプロセスと呼ばれます。スレッドとは、(少なくとも)メモリ空間を共有し、別のハンドラとハンドラをシグナルする一種のプロセスです。

このようなプロセスにはすべて、システム全体で一意の識別子であるPID(プロセスID)があります。いわゆるスレッドの場合、TID(スレッドID)と呼ばれることもありますが、sysadmin(およびカーネル!)の観点からは、TIDとPIDは同じものです(同じ名前空間を共有します)。

その結果、独自の PID 1を持つため、各「スレッド」を個別に実行でき ます。renice

すべてのPIDを再帰的に見つけるrenice

nic-to-nicedプロセスの子孫(子またはスレッドグループ内)であるすべてのプロセス(「通常」または「スレッド」)のPIDを取得する必要があります。これは再帰的でなければなりません(子供の子供を考慮して)。

アントン・レオンチェフの答えはそうするためのヒントを与えます:のすべてのフォルダー名は、潜在的な子プロセスをリスト/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)代わりに呼び出す必要があります。詳細については、この回答を参照してください。


6

プロセス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(これはで書かれてLinuxの実装のバグであるのsetpriority(2 ))、tidに適用することもでき、スレッドを削除します。@Antonの答えが有効である理由です。

しかし、ほとんどの場合、望ましい結果を達成するための簡単な方法があります。これらのスレッドはすべて、グループリーダーのpidである同じpgidを共有します。次のコマンドを発行することにより、pgidでreniceできます。

$ renice -g <pgid>

同じグループリーダーに依存する他のプロセスを放棄したくない場合は、@ Antonのレシピを使用する必要があります。

$ renice <priority> $(ls -1 /proc/<pid>/task)

または:

$renice <priority> $(ps --no-header -Lo tid <pid>)

また、同じグループの他のプロセス、つまり共有するプロセスが同じpgidを持っていることを知りたい場合があります。あなたが使用することができ、PS(1)をpsグループリーダーによるプロセスを選択することはできませんが、あなたはgrepすることができps、それを行うには。pgid 1908を使用したプロセスは、次のコマンドで提供されます。

$ ps --no-header axo pid,pgid |sed -n '/^ *[0-9][0-9]*  *1908/s/[0-9][0-9]* *$//p'

または、sedよりawkを好む場合:

$ ps --no-header axo pid,pgid|awk '{if ($2=="1908") print $1;}'

これは4.19.4(Debian Stretchの時点では)で正しく動作しないようです: $ renice -n 18 -g 8524 renice: failed to get priority for 8524 (process group ID): No such process $ ps --no-header axo pid,pgid|awk '{if ($2=="8524") print $1;}' Totorのメソッドは/まだ動作しますが:$ /bin/ls /proc/8524/task | /usr/bin/xargs renice 19 2739 (process ID) old priority 19, new priority 19 2740 (process ID) old priority 19, new priority 19 ... / proc、htop、pstreeなどで正しいトップがあることを確認しました-レベルPID。過去1年で何かが変わったのかもしれません。
ビルマクゴニグル

どのようにテストを行ったのかわかりません@bill-mcgonigle。DebianStretchで3つのカーネル4.9.0を試しました。Debianテストに関する4.18.0および4.19.0。そして、上で言ったように機能します。
marcz

私が言ったように、4.19.4のDebian Stretchはコマンドと出力を示しています。違いは4.19.0と4.19.4のように見えますが、そのようなマイナーバージョン間で大きな違いがあることに驚いています。
ビルマクゴニグル

プロセス8524は、すべてのスレッドプロセスTIDまたはLPWのPIDであり、プロセスグループではないため、もちろんすべてのスレッドが見つかります/proc/8524/taskが、renice -g失敗します。プロセスツリーを見ると、1つのスレッドプロセスだけでなく、1つのブランチが同じプロセスグループに属します。の結果をもう一度確認してくださいps -Ljf
marcz

0

reniceを使用する場合、-p(プロセスID)の代わりに-g(プロセスグループ)引数を使用することをお勧めします。bash-fooなしでも同じことを行います。

すなわち

(sudo) renice -n <NEW_PRIORITY> -g <MAIN_PROCESS_ID>

marczの答えはすでにこれに言及しています。
トーター

-1

これが私のスクリプトです:

pgrep -v <PROCESS_NAME> | sudo xargs renice <NEW_PRIORITY>

1
これにより、指定したプロセスを除くすべてのプロセスでreniceが起動します。私はこのコマンドを危険で不適切だと個人的に考えています。
-Totor

彼は-vではなく-wを意味していたのだろうか
Diablo-D3
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.