Jak przywrócić wszystkie wątki (i dzieci) jednego procesu w systemie Linux?


22

Linux nie (jeszcze) postępuje zgodnie ze standardem POSIX.1, który mówi, że a renicena proces wpływa na „wszystkie wątki o zasięgu systemowym w tym procesie”, ponieważ zgodnie z dokumentacją pthreads (7) „wątki nie mają wspólnej dobrej wartości”.

Czasami jednak wygodne może być renice„wszystko” związane z danym procesem (jednym z przykładów byłyby procesy potomne Apache i wszystkie ich wątki). Więc,

  • jak mogę renicewszystkie wątki należące do danego procesu?
  • jak mogę renicewszystkie procesy potomne należące do danego procesu?

Szukam dość łatwego rozwiązania.

Wiem, że grupy procesów mogą czasem być pomocne, jednak nie zawsze pasują do tego, co chcę zrobić: mogą obejmować szerszy lub inny zestaw procesów.

Korzystanie z cgroupzarządzanego przez systemdmoże również być pomocne, ale nawet jeśli chcę o tym usłyszeć, najczęściej szukam „standardowego” rozwiązania.

EDYCJA: również man (7) pthreadsmówi „wszystkie wątki w procesie są umieszczone w tej samej grupie wątków; wszyscy członkowie grupy wątków mają ten sam PID”. Czy w ogóle możliwe jest renicecoś, co nie ma własnego PID?

Odpowiedzi:


19

Możesz użyć, /proc/$PID/taskaby znaleźć wszystkie wątki danego procesu, dlatego możesz użyć

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

do renicewszystkich wątków należących do danego procesu.

W ten sam sposób /proc/$PID/task/$PID/childrenmożna znaleźć wszystkie procesy potomne (lub /proc/$PID/task/*/childrenjeśli chcesz wszystkie procesy potomne wszystkich wątków danego procesu).

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

man (7) pthreadsmówi o bieżącej implementacji (NPTL): „wszystkie wątki w procesie są umieszczone w tej samej grupie wątków; wszyscy członkowie grupy wątków mają ten sam PID” i „Wątki nie mają wspólnej dobrej wartości”. Jak w takim razie zrestartować wątek, który nie ma własnego PID, kiedy reniceużywa do tego PID?
— Totor,

Próbowałem renice na identyfikator wątku, i to zgłasza 24995 (process ID) old priority 0, new priority -10. 24995 nie pojawia się ps, więc nie jest to proces. Może wątki odnawiające rzeczywiście działają?
— Stefan Reich

9

Dobra wartość czy udziały w CPU?

Należy pamiętać, że w dzisiejszych czasach ładne wartości mogą nie być tak istotne w całym systemie, ze względu na automatyczne grupowanie zadań, szczególnie podczas korzystania z systemd . Więcej informacji można znaleźć w tej odpowiedzi .

Różnica między wątkami i procesami

Ważne pytanie w systemie Linux, ponieważ dokumentacja utrwala wątpliwości (na przykład wątki nieposiadające własnego PID).

Uwaga: ta odpowiedź dokładnie wyjaśnia wątki systemu Linux.

W skrócie: jądro obsługuje tylko „elementy uruchamialne”, to znaczy coś, co można uruchomić i zaplanować . Jeśli chodzi o jądro, te byty nazywane są procesami. Wątek jest rodzajem procesu, który dzieli (przynajmniej) przestrzeń pamięci i procedury obsługi sygnałów z innym.

Każdy taki proces ma unikalny w całym systemie identyfikator: PID (identyfikator procesu). W przypadku tak zwanych wątków jest czasami nazywany TID (identyfikator wątku), ale z punktu widzenia sysadmin (i jądra!) TID i PID są tym samym (dzielą tę samą przestrzeń nazw).

W rezultacie możesz renice każdy „wątek” osobno, ponieważ ma swój własny PID 1 .

Znajdowanie wszystkich PID-ów renice rekurencyjnie

Musimy uzyskać PID wszystkich procesów („normalnych” lub „wątków”), które są potomkami (dzieci lub w grupie wątków) procesu, który ma być poprawiony. Powinno to być rekurencyjne (biorąc pod uwagę dzieci dzieci).

Odpowiedź Antona Leontiewa daje podpowiedź: wszystkie nazwy folderów /proc/$PID/task/to PID wątków zawierający childrenplik z listą potencjalnych procesów potomnych.

Jednak brakuje mu rekurencyjności, więc oto szybki i brudny skrypt powłoki, aby je znaleźć:

#!/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

Jeśli proces PID 1234 jest tym, który chcesz rekurencyjnie miły, teraz możesz:

renice -n 15 -p $(/path/to/findchildren.sh 1234)

1 Zauważ, że dla zgodności z POSIX, wywołanie getpid(2)w wątku nie da ci ogólnosystemowego unikalnego ID (PID) tego uruchamialnego bytu, ale raczej PID głównego procesu w „grupie wątków”. Zamiast tego musisz zadzwonić gettid(2). Zobacz tę odpowiedź, aby uzyskać więcej informacji.


6

Nie powinniśmy mylić PID procesu i identyfikatora wątku zapisanego TID lub komendy ps LPW. sPolecenie ma opcje do wyświetlania wątków i pod toplub htopprzełączać pomiędzy wątkami i procesu przez Hliście. Jak wcześniej powiedział @Totor, z NPTL, która jest bieżącą implementacją z jądrem> 2.6, wszystkie wątki mają ten sam pid, ale mają wyraźny tid. Wyświetlane są wszystkie wątki procesu według:

$ ps -Ljf <pid>

Te tid są nazwami katalogów pod /proc/<pid>/taski nawet jeśli renice (1) mówi, że domyślnym argumentem jest pid po zastosowaniu do pid, to renice tylko główny wątek (jest to błąd w implementacji linuxa napisany w setpriority (2) ) ), można go również zastosować do przyprawy i ponownie nićmi nitkę. Właśnie dlatego odpowiedź @Anton jest ważna.

Ale najczęściej istnieje łatwiejszy sposób na osiągnięcie pożądanego rezultatu, wszystkie te wątki mają ten sam pgid, który jest pid lidera grupy; możesz ponownie zareagować pgid, wydając:

$ renice -g <pgid>

Jeśli nie chcesz ponownie uruchamiać innego procesu zależnego od tego samego lidera grupy, musisz użyć przepisu @ Antona:

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

lub:

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

Możesz także chcieć dowiedzieć się, jakie są inne procesy w tej samej grupie niż proces, który chcesz ponownie uruchomić, to znaczy procesy, które współużytkują mają ten sam pgid. Możesz użyć ps (1) , psnie pozwala wybrać procesów według lidera grupy, ale możesz to zrobić grep a ps. Procesy z pgid 1908zostaną podane przez polecenie:

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

lub jeśli wolisz awk niż sed:

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

To wydaje się nie działać poprawnie w 4.19.4 (Debian Stretch na razie): $ 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;}' Podczas gdy metoda Totora działa / nadal działa: $ /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 ... Potwierdziłem za pomocą / proc, htop, pstree itp., Że mam poprawne top- poziom PID. Może coś się zmieniło w ciągu ostatniego roku.
— Bill McGonigle

Nie wiem, jak zrobiłeś test @ bill-mcgonigle, właśnie próbowałem z trzema jądrami 4.9.0 na Debian Stretch; 4.18.0 i 4.19.0 dotyczące testowania Debiana; I działa, jak powiedziałem powyżej.
— marcz

Tak jak powiedziałem, Debian Stretch na 4.19.4 z pokazanymi poleceniami i danymi wyjściowymi; różnica wydaje się wynosić 4.19.0 w porównaniu z 4.19.4, ale jestem zaskoczony, że między tak małymi wersjami nastąpiłaby duża zmiana.
— Bill McGonigle

Myślę, że twój proces 8524 jest PID wszystkich wątków procesu TID lub LPW, ale nie grupy procesów, więc oczywiście znajdziesz wszystkie wątki, /proc/8524/taskale renice -gzawiodły. Kiedy patrzysz na drzewo procesów, jedna gałąź znajduje się w tej samej grupie procesów, a nie tylko jeden proces wątkowy. Spróbuj ponownie sprawdzić wynik ps -Ljf.
— marcz

0

Chciałbym polecić użycie argumentu -g (grupy procesów) zamiast -p (identyfikatory procesów) podczas używania renice. Robi to samo bez bash-foo.

to znaczy

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

Odpowiedź marcz już o tym wspomina.
— Totor

-1

Oto mój skrypt:

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

1
To uruchamia renice na każdym procesie z wyjątkiem tego, który nazwiesz. Osobiście uważam to polecenie za niebezpieczne i nieodpowiednie.
— Totor

Zastanawiam się, czy miał na myśli -w nie -v
— Diablo-D3
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.