การส่ง kill -9 ไปยังกระบวนการไม่ต้องการความร่วมมือของกระบวนการ (เช่นการจัดการสัญญาณ) มันแค่ฆ่ามันออกไป
คุณกำลังสันนิษฐานว่าเพราะสัญญาณบางอย่างสามารถถูกจับได้และไม่สนใจพวกมันล้วนเกี่ยวข้องกับความร่วมมือ แต่ตามman 2 signal
" สัญญาณ SIGKILL และ SIGSTOP ไม่สามารถจับหรือเพิกเฉยได้" SIGTERM สามารถถูกจับได้ซึ่งเป็นสาเหตุว่าทำไมที่ราบkill
ไม่ได้มีประสิทธิภาพเสมอไป - โดยทั่วไปนี่หมายถึงบางสิ่งในตัวจัดการของกระบวนการผิดพลาด 1
หากกระบวนการไม่ได้ (หรือไม่สามารถกำหนดตัวจัดการสำหรับสัญญาณที่กำหนดได้เคอร์เนลจะทำการกระทำเริ่มต้น ในกรณีของ SIGTERM และ SIGKILL นี่คือการยกเลิกกระบวนการ (เว้นแต่ว่า PID ของมันคือ 1; เคอร์เนลจะไม่ยุติinit
) 2 หมายถึงการจัดการไฟล์ถูกปิดหน่วยความจำของมันจะถูกปิดหน่วยความจำของมันกลับไปยังกลุ่มระบบ เด็ก ๆ ได้รับการสืบทอดโดย init เป็นต้นเช่นเดียวกับที่เรียกexit
(ดูman 2 exit
) กระบวนการไม่มีอยู่อีกต่อไป - เว้นแต่ว่ามันจะกลายเป็นซอมบี้ซึ่งในกรณีนี้มันยังคงอยู่ในตารางกระบวนการของเคอร์เนลที่มีข้อมูลบางอย่าง ที่เกิดขึ้นเมื่อผู้ปกครองไม่ได้wait
และจัดการกับข้อมูลนี้อย่างถูกต้อง อย่างไรก็ตามกระบวนการซอมบี้จะไม่มีการจัดสรรหน่วยความจำใด ๆ อีกต่อไปดังนั้นจึงไม่สามารถดำเนินการต่อได้
มีบางสิ่งที่เหมือนตารางทั่วโลกในหน่วยความจำที่ลีนุกซ์อ้างอิงทรัพยากรทั้งหมดที่เกิดขึ้นจากกระบวนการและเมื่อฉัน "ฆ่า" กระบวนการลีนุกซ์จะผ่านตารางนั้นและปลดปล่อยทรัพยากรทีละตัว?
ฉันคิดว่ามันแม่นยำพอ หน่วยความจำกายภาพถูกติดตามโดยหน้า (หนึ่งหน้ามักจะมีขนาดเท่ากับ 4 KB) และหน้าเหล่านั้นจะถูกนำมาจากและกลับสู่กลุ่มรวม มันซับซ้อนกว่าเล็กน้อยในการที่เพจที่ถูกปล่อยบางหน้าจะถูกแคชในกรณีที่จำเป็นต้องใช้ข้อมูลอีกครั้ง (นั่นคือข้อมูลที่อ่านจากไฟล์ที่มีอยู่แล้ว)
หน้าพูดคุยเกี่ยวกับ "สัญญาณ" แต่แน่นอนว่ามันเป็นเพียงนามธรรม
แน่นอนว่าสัญญาณทั้งหมดเป็นนามธรรม มันเป็นแนวคิดเช่นเดียวกับ "กระบวนการ" ฉันกำลังเล่นความหมายเล็กน้อย แต่ถ้าคุณหมายถึง SIGKILL นั้นมีคุณภาพแตกต่างจาก SIGTERM ดังนั้นใช่และไม่ใช่ ใช่ในแง่ที่ไม่สามารถจับได้ แต่ไม่มีในแง่ที่ว่าทั้งคู่เป็นสัญญาณ โดยการเปรียบเทียบแอปเปิ้ลไม่ได้เป็นสีส้ม แต่แอปเปิ้ลและส้มเป็นไปตามคำจำกัดความของผลไม้ทั้งสอง SIGKILL ดูเป็นนามธรรมมากกว่าเพราะคุณไม่สามารถจับมันได้ แต่มันก็ยังเป็นสัญญาณ นี่คือตัวอย่างของการจัดการ SIGTERM ฉันแน่ใจว่าคุณเคยเห็นสิ่งเหล่านี้มาก่อน:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
void sighandler (int signum, siginfo_t *info, void *context) {
fprintf (
stderr,
"Received %d from pid %u, uid %u.\n",
info->si_signo,
info->si_pid,
info->si_uid
);
}
int main (void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = sighandler;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &sa, NULL);
while (1) sleep(10);
return 0;
}
กระบวนการนี้จะนอนหลับตลอดไป คุณสามารถเรียกใช้มันใน terminal และส่ง SIGTERM kill
กับ มันคายสิ่งต่าง ๆ เช่น:
Received 15 from pid 25331, uid 1066.
1,066 เป็น UID ของฉัน PID จะเป็นของเชลล์ที่kill
ถูกเรียกใช้งานหรือ PID ของการฆ่าถ้าคุณแยกมัน ( kill 25309 & echo $?
)
อีกครั้งไม่มีจุดในการตั้งค่าตัวจัดการสำหรับ SIGKILL เพราะจะไม่ทำงาน 3ถ้าฉันkill -9 25309
กระบวนการจะยุติ แต่นั่นยังคงเป็นสัญญาณ เมล็ดมีข้อมูลเกี่ยวกับที่ส่งสัญญาณสิ่งที่ชนิดของสัญญาณมันเป็น ฯลฯ
1. ถ้าคุณไม่ได้มองไปที่รายการที่เป็นไปได้สัญญาณkill -l
ให้ดู
2. ข้อยกเว้นอื่น ๆ ตามที่ Tim Post กล่าวถึงด้านล่างนี้ใช้กับกระบวนการในโหมดสลีปที่ไม่สามารถขัดจังหวะได้ สิ่งเหล่านี้ไม่สามารถถูกปลุกให้ตื่นขึ้นได้จนกว่าปัญหาพื้นฐานจะได้รับการแก้ไขและมีสัญญาณทั้งหมด (รวมถึง SIGKILL) รอการตัดบัญชีในช่วงเวลานั้น กระบวนการไม่สามารถสร้างสถานการณ์นั้นได้ตามวัตถุประสงค์
3. สิ่งนี้ไม่ได้หมายความว่าการใช้kill -9
เป็นสิ่งที่ควรทำในทางปฏิบัติ exit()
จัดการตัวอย่างของฉันเป็นคนหนึ่งที่ไม่ดีในแง่ที่ว่ามันไม่ได้นำไปสู่การ วัตถุประสงค์ที่แท้จริงของตัวจัดการ SIGTERM คือการให้โอกาสในการทำสิ่งต่าง ๆ เช่นล้างไฟล์ชั่วคราวจากนั้นออกโดยสมัครใจ หากคุณใช้kill -9
มันจะไม่ได้รับโอกาสนี้ดังนั้นให้ทำเช่นนั้นหากส่วน "ออกโดยสมัครใจ" ดูเหมือนจะล้มเหลว
kill -9
อ้างอิง