लिनक्स पर एक प्रक्रिया के सभी थ्रेड्स (और बच्चे) का नाम कैसे बदलें?


22

लिनक्स (अभी तक) POSIX.1 मानक का पालन नहीं करता है जो कहता है कि एक reniceप्रक्रिया पर "प्रक्रिया में सभी सिस्टम गुंजाइश थ्रेड्स" को प्रभावित करता है, क्योंकि pthreads (7) डॉक्टर के अनुसार "थ्रेड्स एक सामान्य अच्छा मूल्य साझा नहीं करते हैं"।

हालांकि, कभी-कभी, यह reniceकिसी दिए गए प्रक्रिया से संबंधित "सब कुछ" के लिए सुविधाजनक हो सकता है (एक उदाहरण अपाचे बच्चे की प्रक्रिया और उनके सभी धागे होंगे)। इसलिए,

  • मैं दी गई प्रक्रिया से संबंधित reniceसभी सूत्र कैसे बना सकता हूं ?
  • मैं reniceकिसी प्रक्रिया से संबंधित सभी बाल प्रक्रियाएं कैसे कर सकता हूं ?

मैं एक काफी आसान समाधान की तलाश में हूं।

मुझे पता है कि प्रक्रिया समूह कभी-कभी सहायक हो सकते हैं, हालांकि, वे हमेशा उस चीज से मेल नहीं खाते हैं जो मैं करना चाहता हूं: वे प्रक्रियाओं के एक व्यापक या अलग सेट को शामिल कर सकते हैं।

किसी cgroupद्वारा प्रबंधित का उपयोग करना systemdभी सहायक हो सकता है, लेकिन भले ही मैं इसके बारे में सुनने के लिए इच्छुक हूं, मैं ज्यादातर "मानक" समाधान की तलाश कर रहा हूं।

EDIT: यह भी man (7) pthreadsकहता है , "एक प्रक्रिया में सभी थ्रेड्स को एक ही थ्रेड समूह में रखा जाता है, एक थ्रेड समूह के सभी सदस्य एक ही PID को साझा करते हैं"। तो, क्या यह भी संभव है कि reniceऐसा कुछ नहीं है जो स्वयं पीआईडी ​​है?

जवाबों:


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वर्तमान (एनपीटीएल) के कार्यान्वयन के बारे में कहते हैं: "एक प्रक्रिया में सभी थ्रेड्स को एक ही थ्रेड समूह में रखा जाता है, एक थ्रेड समूह के सभी सदस्य एक ही पीआईडी ​​को साझा करते हैं" और "थ्रेड्स एक सामान्य अच्छा मूल्य साझा नहीं करते हैं"। फिर, आप एक थ्रेड का नाम कैसे बदल सकते हैं, जिसमें खुद का पीआईडी ​​नहीं है, जब reniceऐसा करने के लिए पीआईडी ​​का उपयोग करता है?
टॉटर

मैंने एक थ्रेड आईडी पर नाम बदलने की कोशिश की, और यह रिपोर्ट करता है 24995 (process ID) old priority 0, new priority -10। 24995 में प्रकट नहीं होता है ps, इसलिए यह एक प्रक्रिया नहीं है। शायद renice-ing धागे वास्तव में काम करता है?
स्टीफन रीच

9

अच्छा मूल्य या सीपीयू शेयर?

कृपया ध्यान दें कि आजकल, अच्छे मान इतने प्रासंगिक "सिस्टम-वाइड" नहीं हो सकते हैं, क्योंकि स्वचालित कार्य समूहन, सिस्टम के उपयोग के दौरान स्पष्ट रूप से । अधिक जानकारी के लिए कृपया इस उत्तर को देखें।

धागे और प्रक्रियाओं के बीच अंतर

लिनक्स पर महत्वपूर्ण सवाल, क्योंकि प्रलेखन संदेह को समाप्त करता है (उदाहरण के लिए अपने स्वयं के पीआईडी ​​नहीं होने के बारे में)।

नोट: यह उत्तर लिनक्स थ्रेड्स को सटीक रूप से बताता है।

संक्षेप में: कर्नेल केवल " रन करने योग्य निकाय" को संभालता है, अर्थात, कुछ ऐसा जिसे चलाया और शेड्यूल किया जा सकता है । कर्नेल वार, इन संस्थाओं को प्रक्रिया कहा जाता है। एक धागा, सिर्फ एक तरह की प्रक्रिया है जो एक दूसरे के साथ मेमोरी स्पेस और सिग्नल हैंडलर को साझा करता है।

इस तरह की हर प्रक्रिया में एक प्रणाली-व्यापी विशिष्ट पहचानकर्ता है: PID (प्रोसेस आईडी)। तथाकथित थ्रेड्स के लिए, इसे कभी-कभी TID (थ्रेड आईडी) कहा जाता है, लेकिन sysadmin (और कर्नेल!) के दृष्टिकोण से, TID और PID एक ही चीज़ हैं (वे एक ही नाम स्थान साझा करते हैं)।

नतीजतन, आप प्रत्येक "थ्रेड" को व्यक्तिगत रूप से कर सकते renice हैं क्योंकि उनके पास अपना पीआईडी 1 है

सभी पीआईडी ​​को पुनरावृत्ति के लिए ढूँढनाrenice

हमें सभी प्रक्रियाओं ("सामान्य" या "थ्रेड") के पीआईडी ​​प्राप्त करने की आवश्यकता है, जो कि होने वाली प्रक्रिया के वंशज (बच्चे या थ्रेड समूह में) हैं। यह पुनरावर्ती होना चाहिए (बच्चों के बच्चों पर विचार)।

एंटोन लेओनिएव का जवाब ऐसा करने का संकेत देता है: सभी फ़ोल्डर नाम /proc/$PID/task/थ्रेड्स के पीआईडी ​​हैं, जिसमें एक childrenफाइल लिस्टिंग संभावित बच्चों की प्रक्रिया है।

हालाँकि, इसमें पुनरावृत्ति का अभाव है, इसलिए यहां उन्हें खोजने के लिए एक त्वरित और मैला खोल स्क्रिप्ट है:

#!/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)एक थ्रेड के भीतर कॉल करने से आपको इस रन करने योग्य इकाई का सिस्टम-वाइड यूनिक आईडी (पीआईडी) नहीं मिलेगा , बल्कि "थ्रेड ग्रुप" के भीतर मुख्य प्रक्रिया का पीआईडी ​​होगा। आपको gettid(2)इसके बजाय कॉल करना होगा । अधिक जानकारी के लिए यह उत्तर देखें ।


6

हमें प्रक्रिया पीआईडी ​​और थ्रेड आईडी को कभी-कभी टीआईडी ​​या पीएस कमांड एलपीडब्ल्यू में भ्रमित नहीं करना चाहिए। sआदेश प्रदर्शन धागे के विकल्प हैं, और के तहत topया htopआप द्वारा धागे और इस प्रक्रिया के बीच स्विच Hपत्र। जैसा कि पहले @Totor द्वारा बताया गया था, NPTL के साथ, जो कि कर्नेल> 2.6 के साथ वर्तमान कार्यान्वयन है, सभी थ्रेड्स में एक ही पीआईडी ​​है, लेकिन उनके पास एक अलग टिड है। आप किसी प्रक्रिया के सभी सूत्र दिखाते हैं:

$ ps -Ljf <pid>

ये tid के अंतर्गत निर्देशिकाओं के नाम हैं /proc/<pid>/task, और भले ही renice (1) का कहना है कि इसका डिफ़ॉल्ट तर्क एक pid है, जब इसे pid पर लागू किया जाता है, तो यह केवल मुख्य सूत्र का नाम बदल देता है (यह linux कार्यान्वयन में बग है जैसा कि सेटपैरिटी में लिखा गया है (2) ) ), यह भी एक tid पर लागू किया जा सकता है और यह धागे को त्याग देता है। इसीलिए @Anton का उत्तर मान्य है।

लेकिन सबसे अधिक बार वांछित परिणाम प्राप्त करने का एक आसान तरीका है, ये सभी धागे एक ही pgid को साझा करते हैं जो समूह के नेता का पीड; आप जारी करके pgid द्वारा त्याग कर सकते हैं:

$ renice -g <pgid>

यदि आप कुछ अन्य प्रक्रिया का त्याग नहीं करना चाहते हैं जो एक ही समूह के नेता पर निर्भर करता है, तो आपको @ एंटोन की रेसिपी का उपयोग करना होगा:

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

या:

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

आप यह भी जानना चाहते हैं कि जिस समूह का आप नाम बदलना चाहते हैं, उसी समूह की अन्य प्रक्रियाएँ क्या हैं, जो प्रक्रियाएँ हैं, जिनमें समान pgid है। आप ps (1) का उपयोग कर सकते हैं , psसमूह के नेता द्वारा प्रक्रियाओं का चयन करने की अनुमति नहीं देता है, लेकिन आप psइसे करने के लिए grep कर सकते हैं। Pgid के साथ प्रक्रिया 1908कमांड द्वारा दी जाएगी:

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

या यदि आप सेड को 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;}' जबकि टोटर की विधि काम करती है / अभी भी काम करती है: $ /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, आदि के साथ पुष्टि की है कि मेरे पास सही शीर्ष है- स्तर पीआईडी। शायद पिछले वर्ष में कुछ बदल गया है।
बिल मैकगोनिगल

मुझे नहीं पता कि आपने अपना परीक्षण कैसे किया है @ बिल-मैक्गनिगेल, मैंने डेबियन ब्रेट पर तीन गुठली 4.9.0 के साथ कोशिश की; डेबियन परीक्षण पर 4.18.0 और 4.19.0; और यह ऊपर बताए अनुसार काम करता है।
marcz

जैसा कि मैंने कहा, डेबियन खिंचाव 4.19.4 पर कमांड और आउटपुट दिखाया गया है; फर्क 4.19.0 बनाम 4.19.4 लगता है, लेकिन मुझे आश्चर्य है कि ऐसे छोटे संस्करणों के बीच बहुत बदलाव होगा।
बिल मैकगोनिगल

मुझे लगता है कि आपकी प्रक्रिया 8524 सभी थ्रेडेड प्रक्रिया TID या LPW की PID है, लेकिन प्रक्रिया समूह नहीं है, इसलिए निश्चित रूप से आप सभी थ्रेड ढूंढते हैं, /proc/8524/taskलेकिन renice -gअसफल रहते हैं। जब आप एक प्रक्रिया ट्री को देखते हैं तो एक शाखा एक ही प्रक्रिया समूह में होती है, न कि केवल एक थ्रेडेड प्रक्रिया। फिर से परिणाम की जाँच करने का प्रयास करें ps -Ljf
marcz

0

मैं रद्दी का उपयोग करते समय -p (प्रक्रिया आईडी) के बजाय -g (प्रक्रिया समूहों) तर्क का उपयोग करने की सलाह देना चाहूंगा। यह बाश-फू के बिना भी यही काम करता है।

अर्थात

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

marcz के उत्तर में पहले से ही इस बात का उल्लेख है।
टोटर

-1

यहाँ मेरी एक स्क्रिप्ट है:

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

1
यह आपके द्वारा नाम को छोड़कर प्रत्येक प्रक्रियाओं पर नामांकित करता है। मैं वैयक्तिक रूप से इस आदेश को खतरनाक और अपर्याप्त मानता हूं।
टॉटर

मुझे आश्चर्य है कि अगर वह मतलब नहीं था, तो -v
डियाब्लो-डी 3
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.