กระบวนการสามารถถูกแช่แข็งชั่วคราวใน linux หรือไม่?


53

ฉันสงสัยว่ามีวิธีที่จะหยุดกระบวนการใด ๆ เป็นระยะเวลาหนึ่งหรือไม่?

สิ่งที่ฉันหมายถึงคือ: เป็นไปได้หรือไม่ที่แอปพลิเคชันหนึ่ง (อาจใช้งานเป็น root) เพื่อหยุดการดำเนินการของกระบวนการที่กำลังรันอยู่ (กระบวนการใด ๆ ทั้ง GUI และบรรทัดคำสั่ง) แล้วหยุดทำงานในภายหลัง กล่าวอีกนัยหนึ่งฉันไม่ต้องการให้กระบวนการบางอย่างถูกจัดตารางเวลาโดย linux scheduler ในระยะเวลาหนึ่ง

คำตอบ:


81

ดูที่นี่

มีสัญญาณสองสัญญาณที่สามารถหยุดการทำงานของกระบวนการได้ หนึ่งคือ "สง่างาม" และหนึ่งคือ "พลัง"

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

"แรง" คือSIGSTOPและวัตถุประสงค์ของมันคือเพื่อระงับเธรดสเปซผู้ใช้ทั้งหมดที่เกี่ยวข้องกับกระบวนการนั้น มันเป็นเพียงเป็นไปไม่ได้สำหรับกระบวนการที่จะไม่สนใจSIGSTOPมันเป็นมันจะไม่สนใจSIGKILL(หลังฆ่ากระบวนการอย่างแข็งขัน)

ในการส่งสัญญาณโดยพลการใด ๆ รวมทั้งคนที่กล่าวถึงที่นี่คุณสามารถใช้โปรแกรมเช่นkill, killallหรือpkill; kill(2)หรือใช้การโทรระบบ ดู manpages ของระบบปฏิบัติการของคุณสำหรับรายละเอียดเกี่ยวกับแพลตฟอร์ม / สถาปัตยกรรม / เวอร์ชันที่ขึ้นกับเวอร์ชันและ errata เกี่ยวกับข้อใดข้อหนึ่งข้างต้น โปรดทราบว่าคำว่า "kill" ในคำสั่งเหล่านี้ทั้งหมดและ syscall เป็นชื่อเรียกที่ไม่ถูกต้อง คำสั่งเหล่านี้ไม่ได้ออกแบบมาเฉพาะเพื่อยุติกระบวนการ พวกเขาสามารถทำได้โดยการส่งสัญญาณบางอย่าง; แต่สัญญาณยังสามารถใช้สำหรับการทำงานอื่น ๆ นอกเหนือจากการยกเลิกกระบวนการ ตัวอย่างเช่นSIGSTOPหยุดกระบวนการไว้ชั่วคราวและเป็นเพียงหนึ่งในสัญญาณที่สามารถส่งได้ด้วยวิธีนี้

ในการเพิ่มเงื่อนไขของการดำเนินการต่อโดยอัตโนมัติหลังจากผ่านช่วงเวลาหนึ่งไปแล้วคุณจะต้องใช้กระบวนการตรวจสอบบางประเภทที่ยังคงทำงานอยู่และตั้งเวลาเพื่อปลุกกระบวนการตรวจสอบซึ่งจะเป็นการเรียกkill(2)อีกครั้งและ ส่งSIGCONTสัญญาณไปยังกระบวนการที่หยุดทำงานเพื่อร้องขอเคอร์เนลเพื่อดำเนินการต่อ โปรดทราบว่า Linux มีกลไกการจับเวลาหลายอย่างที่มีความแม่นยำและความแม่นยำหลายระดับ นอกจากนี้หากระบบของคุณไม่ว่างมากกระบวนการตรวจสอบของคุณอาจไม่ทำงานจนกว่าจะถึงเวลาที่กำหนดหลังจากหมดเวลาดังนั้นการปลุกอาจล่าช้า

หากคุณขึ้นอยู่กับความแม่นยำถูกต้องมากของการระงับและการเริ่มต้นใหม่ของกระบวนการระงับคุณอาจจำเป็นต้องเรียกใช้โปรแกรมตรวจสอบของคุณมีสิทธิ์ในเวลาจริง (ดูmanpage นี้ในsched_setscheduler(2)ข้อมูลเกี่ยวกับการดำเนินการของคุณแบบ real-time) นอกจากนี้คุณยังสามารถใช้ความละเอียดสูงตัวจับเวลาคุณลักษณะของลินุกซ์ (ซึ่งจะใช้ได้เฉพาะเมื่อฮาร์ดแวร์ของคุณให้การสนับสนุนสำหรับพวกเขา) ในการรวมกันด้วยการตั้งเวลาแบบ real-time เพื่อให้ได้มากที่ถูกต้องแม่นยำย่อยมิลลิวินาทีกับระยะเวลาแล้ว ปลุกและส่งสัญญาณเพื่อให้กระบวนการกลับมาทำงานได้อย่างรวดเร็ว

คุณไม่ได้ระบุว่าคุณต้องการใช้เทคโนโลยีใดในการดำเนินการนี้ อย่างน้อยที่สุดคุณจะต้องใช้สคริปต์ทุบตีอย่างน้อยถึงแม้ว่าคุณจะไม่สามารถทำให้ได้จังหวะที่ดี นี่คือ "สคริปต์" ทุบตี (ยังไม่ทดลองดังนั้นโปรดระวัง) ซึ่งเป็นเพียงหลักฐานของแนวคิดการสืบค้นของคุณ หากคุณต้องการเวลาที่แม่นยำคุณจะต้องเขียนโปรแกรมอาจเป็นภาษา C / C ++ หรือภาษาพื้นเมืองอื่นและใช้การตั้งเวลาและ hrtimers แบบเรียลไทม์

#!/bin/bash
#This is the process you want to suspend.
screen -mdS child bash -c "cat /dev/urandom | base64"
#This is the process ID of the child process
THEPID=$(screen -list | grep child | cut -f1 -d'.' | sed 's/\W//g')
#Send SIGSTOP to the child process.
kill -SIGSTOP ${THEPID}
#Now it is suspended. This process will sleep for 10 seconds asynchronously, then resume the process.
screen -mdS monitor bash -c "sleep 10; kill -SIGCONT ${THEPID}"

โปรดทราบว่าสคริปต์จะสิ้นสุดและสคริปต์ควบคุมจะสิ้นสุดลง แต่เนื่องจากการscreenควบคุมกระบวนการตรวจสอบสคริปต์จะยังคงทำงานในพื้นหลังเป็นเวลา 10 วินาที (ขึ้นอยู่กับอาร์กิวเมนต์ที่ส่งผ่านไปsleep) แล้วตื่นขึ้นมาและดำเนินการต่อกระบวนการลูก แต่จะนานหลังจากสคริปต์ควบคุมสิ้นสุดลง ถ้าคุณต้องการซิงโครนัสรอเวลาที่จะผ่านไปเพียงแค่ละเว้นการโทรครั้งที่สองไปscreenแล้วทำการโค้ด sleep และ kill ลงในสคริปต์ควบคุม

คุณสามารถทดสอบว่ากระบวนการนั้นจริงแล้วถูกระงับโดยการเรียกใช้

screen -rS child

หลังจากที่คุณเริ่มสคริปต์นี้ คุณจะไม่เห็นอะไรเลยบนคอนโซล จากนั้นหลังจากตัวจับเวลาหมดอายุ (10 วินาที) มันจะทำให้หน้าจอของคุณเต็มไปด้วยข้อมูล base64 (ตัวอักษรแบบสุ่มจาก 0-9 และ AF) กด Ctrl + C เพื่อออก


คำตอบที่สมบูรณ์มากดีมากรวมถึง PoC bash snippet ดี!
fgysin

หากกระบวนการได้รับการแช่แข็งในช่วงกลางของเครือข่ายเช่นการเชื่อมต่อ TCP เมื่อมันได้รับอย่างต่อเนื่องเซสชันเครือข่ายที่อาจเกิดความเสียหายหรือลดลง? มีพฤติกรรมที่กำหนดไว้สำหรับสิ่งนี้หรือไม่?
CMCDragonkai

@cmcdragonkai เนื่องจากกระบวนการที่หยุดทำงานในขณะที่ไม่ได้ทำงานจะไม่สามารถอ่านหรือเขียนไปยัง fd ใด ๆ ได้ แต่เคอร์เนลจะทำการถ่ายโอนไบต์จนกว่าบัฟเฟอร์จะเต็มในเซสชัน TCP นั่นคือไม่มีการถ่ายโอนระหว่างพื้นที่เคอร์เนลและพื้นที่ผู้ใช้ กระบวนการแช่แข็งตรวจสอบที่แตกต่างกันhttps://www.kernel.org/doc/Documentation/power/freezing-of-tasks.txt
Nizam Mohamed

ฉันได้พบว่าการเชื่อมต่อ TCP สามารถดำเนินการต่อหลังจากนำกระบวนการกลับไปสู่เบื้องหน้า (ไทม์เอาต์เป็นแอปพลิเคชั่นเฉพาะมี TCP keepalive แต่ยังเป็นระดับแอปพลิเคชัน keepalive) กระบวนการแช่แข็งดูเหมือนว่าจะหมายถึงเมื่อคอมพิวเตอร์อยู่ในโหมดไฮเบอร์เนตหรือโหมดสลีป นั่นถูกต้องใช่ไหม?
CMCDragonkai

สคริปต์นี้ไม่มีผลกับรหัสที่ไม่ทำงานร่วมกัน: gist.github.com/ceremcem/864dd94b52ffe7b18da29558df4f1f5b
ceremcem

14

ใช่คุณสามารถทำได้โดยการส่งสัญญาณSTOPไปยังกระบวนการเพื่อหยุดการทำงานชั่วคราวและจากนั้นดำเนินการต่อเพื่อดำเนินการต่อ

การใช้งาน:

kill -STOP <pid>

kill -CONT <pid>

11

หากคุณมีคำจำกัดความที่ "หยุด" อย่างหลวม ๆ คุณอาจตรวจสอบreniceคำสั่ง

Renice ช่วยให้คุณสามารถเปลี่ยนลำดับความสำคัญการจัดตารางเวลาของกระบวนการทำงาน

ค่า nice ของกระบวนการปกติคือ 0 การเพิ่มค่า nice ทำให้ process ดีกว่าเช่นเดียวกับใน "ทำไมคุณไม่ไปก่อน" ในขณะที่การลดค่า nice ทำให้กระบวนการดีน้อยลงเช่นเดียวกับที่ "ออกไปให้พ้นทางของฉันฉันกำลังรีบ" ช่วงค่าที่ดีคือ -20 ถึง 19

ทุกคนสามารถสร้างกระบวนการของตัวเองได้ดีกว่า มีเพียงรูทเท่านั้นที่สามารถทำให้กระบวนการดีขึ้นหรือเปลี่ยนผู้ใช้คนอื่นให้ประมวลผลได้

หากคุณตั้งค่าโปรเซสที่ดีเป็น 19 จะทำงานเฉพาะเมื่อไม่มีสิ่งใดในระบบที่ต้องการ

นี่คือตัวอย่างการเรียกใช้บนกล่อง linux ของฉัน

ใช้ps -lและดูที่คอลัมน์ NI เพื่อดูกระบวนการที่คุ้มค่า

-> ps -l
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 75 0 - 16547 รอ pts / 0 bash
0 T 29190 1105 402 0 75 0 - 23980 finish pts / 0 vim
0 R 29190 794 402 0 76 0 - 15874 - pts / 0 ps

การรันrenice +10บนกระบวนการ vim ทำให้การรันที่ระดับความสำคัญต่ำกว่า

-> renice +10 -p 1105
1105: ลำดับความสำคัญเก่า 0 ลำดับความสำคัญใหม่ 10

-> ps -l
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 76 0 - 16547 รอ pts / 0 bash
0 T 29190 1105 402 0 95 10 - 23980 finish pts / 0 vim
0 R 29190 1998 402 0 78 0 - 15874 - pts / 0 ps

สมมติว่าคุณสามารถยืด "หยุด" เพื่อหมายถึง "ไม่รบกวนคนอื่นในระบบ" คุณสามารถเขียนสคริปต์บางอย่างเช่น:

renice 20 -p <pid ที่น่าสนใจ>
หลับ <ระยะเวลา>
renice 0 -p <pid ที่น่าสนใจ>

(อย่าลืมเรียกใช้เป็นรูท)


โปรดทราบว่าฉันใช้เสรีภาพบางส่วนกับps -lผลลัพธ์ด้านบนเพื่อรับคอลัมน์ที่น่าสนใจเพื่อแสดงอย่างชัดเจนในกล่องสีฟ้าเล็ก ๆ :)

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