Linux'ta bir sürecin tüm iş parçacıklarını (ve çocuklarını) nasıl yeniliyoruz?


22

Linux (henüz) POSIX.1 standardı takip etmez diyor bir o reniceuygun çünkü bir süreç "sürecinde tüm sistem kapsam konuları" etkiler pthreads (7) doc "ipler ortak güzel değeri paylaşma".

Ancak, bazen, renicebelirli bir işlemle ilgili "her şey" için uygun olabilir (bir örnek Apache alt işlemleri ve tüm konuları olabilir). Yani,

  • Belirli bir sürece ait renicetüm konuları nasıl yapabilirim ?
  • Belirli bir sürece ait renicetüm alt işlemleri nasıl yapabilirim ?

Oldukça kolay bir çözüm arıyorum.

Süreç gruplarının bazen yardımcı olabileceğini biliyorum , ancak onlar yapmak istediklerimle her zaman eşleşmiyorlar: daha geniş veya farklı süreçler içerebilirler.

Bir cgroupyönetilen kullanmak systemdda yardımcı olabilir, ancak duymak istesem bile, çoğunlukla "standart" bir çözüm arıyorum.

EDIT: ayrıca, man (7) pthreads"bir işlemdeki tüm iş parçacıklarının tümü aynı iş parçacığı grubuna yerleştirilmiş; iş parçacığı grubunun tüm üyeleri aynı PID'yi paylaşıyor" diyor. Yani, renicekendi PID'sine sahip olmayan bir şey için bile mümkün mü?

Yanıtlar:


19

Sen kullanabilirsiniz /proc/$PID/tasknedenle kullanabilirsiniz, belirli sürecinin tüm konuları bulmak için

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

için renicetüm parçacıkları belirli bir işleme ait.

/proc/$PID/task/$PID/childrenTüm alt işlemleri bulmak için de aynı yöntem kullanılabilir (veya belirli bir işlemin tüm iş parçacıklarının/proc/$PID/task/*/children tüm alt işlemlerini istiyorsanız ).

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

man (7) pthreadsGeçerli (NPTL) uygulama hakkında şunları söylüyor: "bir işlemdeki tüm iş parçacıkları aynı iş parçacığı grubuna yerleştirilmiş; iş parçacığı grubunun tüm üyeleri aynı PID'yi paylaşıyor" ve "Dişler ortak bir hoş değeri paylaşmıyor". Öyleyse, kendi PID'sine sahip olmayan renicebir diziyi, bunu yapmak için bir PID kullandığında nasıl yenileyebilirsiniz ?
Totor

Bir iş parçacığı kimliğinde Renice denedim ve raporlar 24995 (process ID) old priority 0, new priority -10. 24995 görünmüyor ps, bu yüzden bir süreç değil. Belki renice-ing konuları aslında işe yarıyor?
Stefan Reich

9

Güzel değer veya CPU hisseleri?

Günümüzde, özellikle de sistemd kullanılırken otomatik görev gruplaması nedeniyle iyi değerlerin "sistem çapında" çok önemli olmayabileceğini lütfen unutmayın . Lütfen daha fazla ayrıntı için bu cevaba bakınız.

Dişler ve işlemler arasındaki fark

Linux'taki önemli soru, çünkü dokümantasyon şüpheleri sürdürür (örneğin, kendi PID'lerine sahip olmayan konular hakkında).

Not: Bu cevap tam olarak Linux konularını açıklar.

Kısacası: Çekirdek yalnızca "çalıştırılabilir varlıkları", yani çalıştırılabilir ve zamanlanmış bir şeyi işler . Çekirdek bilge, bu varlıklara süreç denir. Bir iş parçacığı, yalnızca en azından bellek alanını ve sinyal işleyicilerini başka biriyle paylaşan bir tür işlemdir.

Böyle bir işlemin sistem genelinde benzersiz bir tanıtıcısı vardır: PID (İşlem Kimliği). Sözde konu başlıkları için, bazen TID (Konu Kimliği) olarak adlandırılır, ancak sysadmin (ve çekirdek!) Bakış açısından, TID ve PID aynı şeydir (aynı ad alanını paylaşırlar).

Sonuç olarak, olabilir renice onların her bir "diş" sahip bireysel çünkü kendi PID 1 .

Tüm PID'leri yinelemeli olarak bulmarenice

İşlenecek sürecin soyundan gelen (çocuklarda veya iş parçacığı grubunda) tüm işlemlerin ("normal" veya "iş parçacığı") PID'lerini almamız gerekir. Bu özyinelemeli olmalı (çocukların çocukları göz önüne alındığında).

Anton Leontiev cevap bu konuda ipucu veriyor: içindeki tüm klasör isimleri, potansiyel çocuk işlemlerini listeleyen /proc/$PID/task/bir childrendosya içeren iş parçacığının PID'sidir .

Ancak özyinelemeden yoksun, bu yüzden onları bulmak için hızlı ve kirli bir kabuk betiği:

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

Yinelemeli olarak güzel olmasını istediğiniz süreç PID 1234 ise, şimdi yapabilirsiniz:

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

1 POSIX uyumu için, çağrıda Not getpid(2)bir iş parçacığı içinde olacak değil bu katedilebilen varlığın sistem genelinde benzersiz kimliği (PID) vermek değil, "iş parçacığı grubu" içinde ana sürecin PID. Bunun gettid(2)yerine aramanız gerekir . Daha fazla bilgi için bu cevaba bakınız .


6

Proses PID ile iplik kimliğini bir zamanlar TID veya ps komutu LPW ile karıştırmamalıyız. sKomut ekranı parçacığı için seçenekler vardır ve altında topveya htopsize Mesajlara ve süreç arasında geçiş Hharfi. @Totor tarafından daha önce de söylendiği gibi, çekirdek> 2.6 olan mevcut uygulama olan NPTL ile, tüm iş parçacıkları aynı iadeye sahiptir, ancak belirgin bir geliri vardır. Bir işlemin tüm iş parçacıklarını şununla göster:

$ ps -Ljf <pid>

Bu tid, altındaki dizinlerin isimleridir /proc/<pid>/taskve renice (1) , varsayılan argümanının bir pid'e uygulandığında bir pid olduğunu söylese bile, sadece ana konuyu yeniler ( bu, linux uygulamasında setpriority'de yazılmış bir hatadır (2) ) ), ayrıca bir dereye uygulanabilir ve ipliği yeniler. Bu nedenle @Anton'ın cevabı geçerlidir.

Ancak çoğu zaman istenen sonucu elde etmenin daha kolay bir yolu vardır, tüm bu iplikler grup liderinin yardımcısı olan aynı pgid'i paylaşır; yayınlayarak pgid ile yenileyebilirsiniz:

$ renice -g <pgid>

Aynı grup liderine bağlı başka bir süreci reddetmek istemiyorsanız, @ Anton'un tarifini kullanmanız gerekir:

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

veya:

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

Aynı grubun diğer işlemlerinin ne olduğunu bilmek isteyebilirsiniz, bu da sizden ayırmak istediğiniz işlemden, yani paylaşılan işlemlerin aynı pgid olduğunu gösterir. Ps (1) kullanabilirsiniz , psgrup liderinin işlem seçmesine izin vermez, ancak bunu psyapmak için a kullanabilirsiniz. Pgid ile işlemler 1908komut tarafından verilecektir:

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

veya sedk'i awk tercih ederseniz:

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

Bu 4.19.4'te doğru bir şekilde çalışmıyor gibi görünüyor (şu andan itibaren 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'un metodu hala çalışıyorsa / hala çalışıyor: $ /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 vb. seviye PID. Belki geçen yıl bir şey değişti.
Bill McGonigle

Testinizi nasıl yaptığınızı bilmiyorum @ bill-mcgonigle, az önce Debian Stretch'te 4.9.0 olan üç çekirdekle denedim; Debian testlerinde 4.18.0 ve 4.19.0; Ve yukarıda söylediğim gibi çalışıyor.
marcz

Dediğim gibi, Debian Stretch 4.19.4'te gösterilen komut ve çıktılarla; fark 4.19.0 vs 4.19.4 gibi görünüyor ancak bu tür küçük sürümler arasında çok fazla değişiklik olacağına şaşırdım.
Bill McGonigle

Sanırım 8524 işleminiz tüm iş parçacığı TID ya da LPW işlemlerinin PID'si, ancak işlem grubu değil, tabii ki tüm ipuçlarını bulabileceğiniz /proc/8524/taskancak renice -gbaşarısız olduğunuz için. Bir işlem ağacına baktığınızda, bir dal yalnızca bir iş parçacığı işleminde değil aynı işlem grubundadır. Sonucunu kontrol etmeyi tekrar deneyin ps -Ljf.
marcz

0

Renice kullanırken -p (işlem kimlikleri) yerine -g (işlem grupları) argümanını kullanmanızı tavsiye ederim. Bu bash-foo olmadan aynı şeyi yapar.

yani

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

marcz 'ın cevabı zaten bundan bahseder.
Totor

-1

İşte benim bir senaryo:

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

1
Bu, sizin isminiz hariç, her işlem için renice başlatır. Ben şahsen bu emri tehlikeli ve yetersiz buluyorum.
Totor

Acaba -v değil -v'yi kastettiğini merak ediyorum
Diablo-D3
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.