Linux에서 하나의 프로세스의 모든 스레드와 하위 프로세스를 처리하는 방법은 무엇입니까?


22

리눅스는 (아직)이 POSIX.1 표준을 따르지 않는 말한다 • 그래도 renice에 따라 때문에, 프로세스에 "이 과정에서 모든 시스템 범위 스레드"에 영향을 의 pthreads (7) 문서 "스레드가 공통의 좋은 가치를 공유하지 않습니다."

그러나 때로는 renice주어진 프로세스와 관련된 "모든 것" 이 편리 할 수 ​​있습니다 (예를 들어 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를 공유합니다"및 "스레드가 공통의 좋은 값을 공유하지 않습니다". 그렇다면 renicePID를 사용하여 자체 PID가없는 스레드를 어떻게 다시 사용할 수 있습니까?
Totor

스레드 ID를 renice하려고 시도했으며보고합니다 24995 (process ID) old priority 0, new priority -10. 에 24995가 표시되지 않으므로 ps프로세스가 아닙니다. 아마도 renice-ing 스레드가 실제로 작동합니까?
Stefan Reich

9

좋은 가치 또는 CPU 공유?

현재 systemd를 사용할 때 자동 작업 그룹화로 인해 좋은 값이 "시스템 전체"와 관련이 없을 수도 있습니다 . 자세한 내용은 이 답변 을 참조하십시오.

스레드와 프로세스의 차이점

Linux에서 중요한 질문은 문서가 의심을 영속시키기 때문입니다 (예를 들어 자체 PID가없는 스레드에 대한).

참고 : 이 답변은 Linux 스레드를 정확하게 설명합니다.

간단히 말해서 커널은 "실행 가능한 엔티티", 즉 실행예약 가능한 것만 처리합니다 . 커널과 관련하여 이러한 엔티티를 프로세스라고합니다. 스레드는 다른 메모리 공간과 신호 처리기를 공유하는 프로세스의 일종입니다.

이러한 모든 프로세스에는 시스템 전체 고유 식별자 인 PID (프로세스 ID)가 있습니다. 이른바 스레드의 경우 TID (Thread ID)라고도하지만 sysadmin (및 커널!)의 관점에서 TID와 PID는 같은 것입니다 (동일한 네임 스페이스를 공유 함).

결과적으로 각각의 "스레드"에는 자체 PID 1 이 있기 때문에 개별적으로 "스레드" 할 수 있습니다 .renice

재귀 적으로 모든 PID 찾기renice

정리할 프로세스의 하위 (자식 또는 스레드 그룹) 인 모든 프로세스 ( "정상"또는 "스레드")의 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)대신 전화해야합니다 . 자세한 내용은 이 답변 을 참조하십시오.


6

프로세스 PID와 스레드 ID를 때때로 TID 또는 ps 명령 LPW로 혼동해서는 안됩니다. 이 s명령에는 스레드를 표시하는 옵션이 있으며 아래 top또는 문자 htop사이에서 스레드와 프로세스를 전환합니다 H. 커널이 2.6보다 큰 현재 구현 인 NPTL을 사용하여 @Totor가 이전에 말했듯이 모든 스레드는 동일한 pid를 갖지만 고유 한 tid를 갖습니다. 다음과 같은 방법으로 프로세스의 모든 스레드를 표시합니다.

$ ps -Ljf <pid>

이 tid는 아래 디렉토리의 이름이며 renice (1) 가 기본 인수가 pid에 적용될 때 기본 인수가 pid라고 말 /proc/<pid>/task하더라도 주 스레드 만 기각합니다 (이것은 setpriority (2 로 작성된 Linux 구현의 버그입니다) ) ), 그것은 또한 tid에 적용될 수 있고 실을 renices합니다. 그래서 @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에서 제대로 작동하지 않는 것 같습니다 (현재 데비안 스트레치) : $ 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. 작년에 뭔가 바뀌었을 수도 있습니다.
Bill McGonigle

나는 당신이 @ bill-mcgonigle @ 테스트를 어떻게했는지 모르겠다. 나는 데비안 스트레치 (Debian Stretch)에서 커널 3.9.0 3 개를 사용해 보았다. 데비안 테스트 4.18.0 및 4.19.0; 그리고 위에서 말했듯이 작동합니다.
marcz

내가 말했듯이, 데비안 스트레치는 4.19.4에서 명령과 출력을 보여주었습니다. 차이는 4.19.0 대 4.19.4 인 것처럼 보이지만 그러한 마이너 버전 사이에 많은 변화가있을 것입니다.
Bill McGonigle

프로세스 8524가 모든 스레드 프로세스 TID 또는 LPW의 PID이지만 프로세스 그룹이 아닌 것 같습니다. 물론 모든 스레드를 찾을 수는 /proc/8524/task있지만 renice -g실패합니다. 프로세스 트리를 볼 때 하나의 분기는 하나의 스레드 프로세스뿐만 아니라 동일한 프로세스 그룹에 있습니다. 의 결과를 다시 확인하십시오 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 -v가 아니라고 생각했는지 궁금합니다.
Diablo-D3
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.