จะยกเลิกการใช้เธรด (และลูก) ทั้งหมดของกระบวนการเดียวบน Linux ได้อย่างไร


22

ลินุกซ์ยังไม่ได้ปฏิบัติตามมาตรฐาน POSIX.1 ซึ่งระบุว่า a reniceในกระบวนการส่งผลกระทบต่อ "เธรดขอบเขตระบบทั้งหมดในกระบวนการ" เนื่องจากตามpthreads (7) doc "เธรดไม่ได้แชร์ค่า nice ที่ดี"

อย่างไรก็ตามบางครั้งมันสามารถสะดวกในการ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 เดียวกัน" และ "เธรดไม่แชร์ค่า nice ที่ดี" จากนั้นคุณจะสามารถยกเลิกเธรดที่ไม่มี PID ของตัวเองได้อย่างไรเมื่อreniceใช้ PID
Totor

ฉันพยายาม renice ใน ID 24995 (process ID) old priority 0, new priority -10ด้ายและรายงาน 24995 ไม่ปรากฏในpsดังนั้นจึงไม่ใช่กระบวนการ อาจจะเป็นการยกเลิกการใช้งานเธรดจริงหรือ
Stefan Reich

9

คุ้มค่าหรือซีพียูใช้ร่วมกัน?

โปรดทราบว่าปัจจุบันค่านิยมที่ดีอาจจะไม่เกี่ยวข้องดังนั้น "ทั้งระบบ" เพราะงานอัตโนมัติการจัดกลุ่ม espacially เมื่อใช้systemd โปรดดูคำตอบนี้สำหรับรายละเอียดเพิ่มเติม

ความแตกต่างระหว่างเธรดและกระบวนการ

คำถามที่สำคัญบน Linux เนื่องจากเอกสารประกอบจะทำให้เกิดข้อสงสัย (เช่นเธรดที่ไม่มี PID ของตัวเอง)

หมายเหตุ: คำตอบนี้อธิบายถึงหัวข้อ Linux อย่างแม่นยำ

กล่าวโดยย่อ: เคอร์เนลจัดการเฉพาะ "เอนทิตีที่เรียกใช้งานได้" ซึ่งก็คือสิ่งที่สามารถรันและกำหนดเวลาได้ เคอร์เนลฉลาด, หน่วยงานเหล่านี้เรียกว่ากระบวนการ เธรดเป็นเพียงกระบวนการที่แบ่งใช้พื้นที่หน่วยความจำ (อย่างน้อย) และตัวจัดการสัญญาณกับอีกกระบวนการหนึ่ง

ทุกกระบวนการดังกล่าวมีตัวระบุที่ไม่ซ้ำกันทั้งระบบ: PID (ID กระบวนการ) สำหรับเธรดที่เรียกว่าบางครั้งเรียกว่า TID (Thread ID) แต่จากมุมมอง sysadmin (และเคอร์เนล!) TID และ PID เป็นสิ่งเดียวกัน (แบ่งเป็นเนมสเปซเดียวกัน)

เป็นผลให้คุณสามารถ reniceแต่ละ "หัวข้อ" รายบุคคลเพราะพวกเขามีของพวกเขาเอง PID 1

ค้นหา PID ทั้งหมดไปยังrenice แบบเรียกซ้ำ

เราจำเป็นต้องได้รับ PID ของกระบวนการทั้งหมด ("ปกติ" หรือ "เธรด") ซึ่งเป็นลูกหลาน (เด็กหรือในกลุ่มเธรด) ของกระบวนการที่ต้องถูกจัดให้อยู่ในสภาพดี สิ่งนี้ควรเป็นแบบเรียกซ้ำ (พิจารณาจากเด็ก ๆ )

คำตอบของAnton Leontievให้คำแนะนำ: ชื่อโฟลเดอร์ทั้งหมด/proc/$PID/task/เป็น PID ของเธรดที่มี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)ภายในเธรดจะไม่ให้ ID ที่ไม่ซ้ำกันทั่วทั้งระบบ (PID) ของเอนทิตีที่รันได้นี้ แต่เป็นการ PID ของกระบวนการหลักภายใน "กลุ่มเธรด" คุณจะต้องโทรgettid(2)แทน ดูคำตอบนี้สำหรับข้อมูลเพิ่มเติม


6

เราไม่ควรสร้างความสับสนให้กับกระบวนการ PID และรหัสเธรดบางครั้งเขียน TID หรือในคำสั่ง ps LPW sคำสั่งมีตัวเลือกในการแสดงผลหัวข้อและภายใต้topหรือhtopคุณสลับระหว่างกระทู้และกระบวนการตามHตัวอักษร ดังที่ก่อนหน้านี้บอกโดย @Totor ด้วย NPTL ซึ่งเป็นการนำไปใช้งานในปัจจุบันด้วยเคอร์เนล> 2.6 เธรดทั้งหมดมี pid เดียวกัน แต่มี tid ที่แตกต่างกัน คุณแสดงเธรดทั้งหมดของกระบวนการโดย:

$ ps -Ljf <pid>

tid เหล่านี้เป็นชื่อของไดเรกทอรีภายใต้/proc/<pid>/taskและแม้ว่าrenice (1)บอกว่าอาร์กิวเมนต์เริ่มต้นของมันคือ pid เมื่อนำไปใช้กับ pid มัน renice เฉพาะเธรดหลัก (นี่เป็นข้อบกพร่องในการใช้งาน linux ตามที่เขียนไว้ในsetpriority ) ) มันยังสามารถนำไปใช้กับ tid และมัน renices ด้าย นั่นเป็นเหตุผลที่คำตอบของ @Anton นั้นถูกต้อง

แต่บ่อยครั้งที่มีวิธีที่ง่ายกว่าในการบรรลุผลลัพธ์ที่ต้องการเธรดเหล่านี้ทั้งหมดใช้ pgid เดียวกันซึ่งเป็น pid ของหัวหน้ากลุ่ม คุณสามารถ renice ด้วย pgid โดยการออก:

$ 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'

หรือถ้าคุณต้องการ awk เพื่อ sed:

$ 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 อาจมีการเปลี่ยนแปลงบางอย่างในปีที่ผ่านมา
Bill McGonigle

ฉันไม่รู้ว่าคุณทำการทดสอบ @ bill-mcgonigle ของคุณได้อย่างไรฉันลองสามเมล็ด 4.9.0 ใน Debian Stretch; 4.18.0 และ 4.19.0 สำหรับการทดสอบเดเบียน และใช้งานได้ตามที่ฉันบอกไว้ข้างต้น
marcz

อย่างที่ฉันพูด Debian Stretch บน 4.19.4 ด้วยคำสั่งและผลลัพธ์ที่แสดง ความแตกต่างนั้นน่าจะเป็น 4.19.0 เทียบกับ 4.19.4 แต่ฉันประหลาดใจที่จะมีการเปลี่ยนแปลงมากมายระหว่างเวอร์ชั่นรอง
Bill McGonigle

ฉันเดาว่ากระบวนการ 8524 ของคุณคือ PID ของกระบวนการเธรดทั้งหมด TID หรือ LPW แต่ไม่ใช่กลุ่มกระบวนการดังนั้นแน่นอนคุณจะพบเธรดทั้งหมดใน/proc/8524/taskแต่renice -gไม่สำเร็จ เมื่อคุณดูที่แผนผังกระบวนการหนึ่งสาขาจะอยู่ในกลุ่มกระบวนการเดียวกันไม่ใช่เพียงกระบวนการเธรดเดียวเท่านั้น ps -Ljfลองอีกครั้งผลของการตรวจสอบ
marcz

0

ฉันอยากจะแนะนำให้ใช้อาร์กิวเมนต์ -g (กลุ่มกระบวนการ) แทน -p (รหัสกระบวนการ) ในขณะที่ใช้ renice มันทำสิ่งเดียวกันโดยไม่ต้องทุบตี

กล่าวคือ

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

คำตอบของmarczพูดถึงเรื่องนี้แล้ว
Totor

-1

นี่คือสคริปต์ของฉัน:

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

1
สิ่งนี้จะเปิดใช้งาน renice ในทุกกระบวนการยกเว้นกระบวนการที่คุณตั้งชื่อ ฉันคิดว่าคำสั่งนี้เป็นอันตรายและไม่เพียงพอ
Totor

ฉันสงสัยว่าเขาหมายถึงอะไร -w ไม่ใช่ -v
Diablo-D3
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.