SIGINT เกี่ยวข้องกับสัญญาณการยุติอื่น ๆ เช่น SIGTERM, SIGQUIT และ SIGKILL อย่างไร


103

ในระบบ POSIX สัญญาณการยุติมักจะมีลำดับดังต่อไปนี้ (ตาม MAN หลายหน้าและ POSIX Spec):

  1. SIGTERM - ขอให้กระบวนการยุติอย่างสุภาพ มันจะยุติลงอย่างสง่างามล้างทรัพยากรทั้งหมด (ไฟล์ซ็อกเก็ตกระบวนการลูก ฯลฯ ) การลบไฟล์ชั่วคราวและอื่น ๆ

  2. SIGQUIT - คำขอที่มีประสิทธิภาพมากขึ้น มันจะยุติการอัปยศโดยยังคงล้างทรัพยากรที่จำเป็นอย่างยิ่งที่ต้องล้างข้อมูล แต่อาจจะไม่ลบไฟล์ชั่วคราวอาจจะเขียนข้อมูลการดีบักไว้ที่ไหนสักแห่ง ในบางระบบจะมีการเขียนคอร์ดัมพ์ (ไม่ว่าแอพจะจับสัญญาณหรือไม่ก็ตาม)

  3. SIGKILL - คำขอที่ทรงพลังที่สุด กระบวนการนี้ไม่ได้ขอให้ทำอะไรเลย แต่ระบบจะล้างกระบวนการไม่ว่าจะเป็นเช่นนั้นหรือไม่ก็ตาม เป็นไปได้มากว่าจะมีการเขียนการถ่ายโอนข้อมูลหลัก

SIGINT เข้ากับภาพนั้นได้อย่างไร? โดยปกติกระบวนการ CLI จะถูกยุติโดย SIGINT เมื่อผู้ใช้เข้าชม CRTL + C อย่างไรก็ตามกระบวนการพื้นหลังสามารถยุติได้โดย SIGINT โดยใช้ยูทิลิตี้ KILL สิ่งที่ฉันมองไม่เห็นในข้อมูลจำเพาะหรือไฟล์ส่วนหัวคือถ้า SIGINT มีกำลังมากกว่าหรือน้อยกว่า SIGTERM หรือมีความแตกต่างระหว่าง SIGINT และ SIGTERM เลย

อัพเดท:

คำอธิบายที่ดีที่สุดของสัญญาณการเลิกจ้างผมพบว่าจนถึงขณะนี้อยู่ในเอกสาร GNU libc อธิบายได้เป็นอย่างดีว่ามีความแตกต่างระหว่าง SIGTERM และ SIGQUIT

กล่าวเกี่ยวกับ SIGTERM:

เป็นวิธีปกติในการขอให้โปรแกรมยุติการทำงานอย่างสุภาพ

และพูดเกี่ยวกับ SIGQUIT:

[... ] และสร้างคอร์ดัมพ์เมื่อยุติกระบวนการเช่นเดียวกับสัญญาณข้อผิดพลาดของโปรแกรม คุณสามารถคิดว่านี่เป็นเงื่อนไขข้อผิดพลาดของโปรแกรมที่ "ตรวจพบ" โดยผู้ใช้ [... ] การล้างข้อมูลบางประเภทควรละเว้นในการจัดการ SIGQUIT ตัวอย่างเช่นหากโปรแกรมสร้างไฟล์ชั่วคราวโปรแกรมควรจัดการกับคำร้องขอการยกเลิกอื่น ๆ โดยการลบไฟล์ชั่วคราว แต่จะดีกว่าถ้า SIGQUIT ไม่ลบออกเพื่อให้ผู้ใช้สามารถตรวจสอบร่วมกับ core ดัมพ์ได้

และ SIGHUP ก็อธิบายได้ดีพอ SIGHUP ไม่ใช่สัญญาณการยุติ แต่เพียงแค่หมายความว่า "การเชื่อมต่อ" กับผู้ใช้ขาดหายไปดังนั้นแอปจึงไม่สามารถคาดหวังให้ผู้ใช้อ่านเอาต์พุตเพิ่มเติมใด ๆ (เช่นเอาต์พุต stdout / stderr) และไม่มีอินพุตที่คาดหวังจาก ผู้ใช้อีกต่อไป สำหรับแอปส่วนใหญ่นั่นหมายความว่าควรเลิกใช้ ในทางทฤษฎีแอปสามารถตัดสินใจได้ว่าจะเข้าสู่โหมด daemon เมื่อได้รับ SIGHUP และตอนนี้ทำงานเป็นกระบวนการเบื้องหลังโดยเขียนเอาต์พุตไปยังไฟล์บันทึกที่กำหนดค่าไว้ สำหรับ daemons ส่วนใหญ่ที่ทำงานอยู่เบื้องหลังแล้ว SIGHUP มักจะหมายความว่าพวกเขาจะตรวจสอบไฟล์คอนฟิกูเรชันอีกครั้งดังนั้นคุณจึงส่งไปยังกระบวนการเบื้องหลังหลังจากแก้ไขไฟล์กำหนดค่า

อย่างไรก็ตามไม่มีคำอธิบายที่เป็นประโยชน์เกี่ยวกับ SIGINT ในหน้านี้นอกเหนือจากที่ส่งโดย CRTL + C มีเหตุผลใดบ้างที่เราจะจัดการ SIGINT ด้วยวิธีที่แตกต่างจาก SIGTERM? ถ้าเป็นเช่นนั้นสาเหตุใดและการจัดการจะแตกต่างกันอย่างไร


1
คำถามที่ดี. ฉันสงสัยว่า Unix cruft ในอดีตจะมีส่วนเกี่ยวข้องกับคำตอบ
Alex B

ฉันรู้ว่าคำถามนี้เก่า แต่ในกรณีที่มีใครมาที่นี่เพื่อดูรายการสัญญาณที่ครอบคลุมสำหรับระบบปฏิบัติการ (Linux) ของคุณสามารถพบได้โดยพิมพ์sudo fuser -lบนพรอมต์คำสั่งของคุณ สำหรับฉันสิ่งนี้จะปรากฏขึ้น:HUP INT QUIT ILL TRAP ABRT IOT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS UNUSED
Nick Bull

3
ลองkill -lดูรายการสัญญาณด้วย
AAAfarmclub

คำตอบ:


89

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

SIGINT และ SIGQUIT มีไว้สำหรับคำร้องขอจากเทอร์มินัลโดยเฉพาะ: สามารถกำหนดอักขระอินพุตเฉพาะเพื่อสร้างสัญญาณเหล่านี้ (ขึ้นอยู่กับการตั้งค่าการควบคุมเทอร์มินัล) การดำเนินการเริ่มต้นสำหรับ SIGINT เป็นการสิ้นสุดกระบวนการประเภทเดียวกับการดำเนินการเริ่มต้นสำหรับ SIGTERM และการดำเนินการที่ไม่สามารถเปลี่ยนแปลงได้สำหรับ SIGKILL การดำเนินการเริ่มต้นสำหรับ SIGQUIT ยังเป็นการยุติกระบวนการ แต่การดำเนินการที่กำหนดการนำไปใช้เพิ่มเติมอาจเกิดขึ้นได้เช่นการสร้างดัมพ์หลัก กระบวนการนี้อาจถูกจับหรือเพิกเฉยหากจำเป็น

SIGHUP อย่างที่คุณพูดมีจุดประสงค์เพื่อระบุว่าการเชื่อมต่อเทอร์มินัลขาดหายไปแทนที่จะเป็นสัญญาณการยุติเช่นนี้ แต่อีกครั้งการดำเนินการเริ่มต้นสำหรับ SIGHUP (หากกระบวนการไม่จับหรือเพิกเฉย) คือการยุติกระบวนการในลักษณะเดียวกับ SIGTERM เป็นต้น

มีตารางในข้อกำหนดPOSIXsignal.hซึ่งแสดงรายการสัญญาณต่างๆรวมถึงการดำเนินการและวัตถุประสงค์เริ่มต้นและบทอินเทอร์เฟซเทอร์มินัลทั่วไปมีรายละเอียดเพิ่มเติมเกี่ยวกับสัญญาณที่เกี่ยวข้องกับเทอร์มินัล


10
นี่คือประเด็นสำคัญ: SIGINT และ SIGQUIT สามารถสร้างได้จากเทอร์มินัลโดยใช้อักขระตัวเดียวในขณะที่โปรแกรมกำลังทำงาน สัญญาณอื่น ๆ จะต้องถูกสร้างขึ้นโดยโปรแกรมอื่นอย่างใดอย่างหนึ่ง (เช่นโดยคำสั่ง kill) SIGINT มีความรุนแรงน้อยกว่า SIGQUIT หลังสร้างการถ่ายโอนข้อมูลหลัก SIGKILL ไม่สามารถติดกับดักได้ SIGHUP จะถูกสร้างขึ้นหากการเชื่อมต่อของคุณวางสาย (หน้าต่างปิด ฯลฯ ) ดังนั้นพวกเขาทั้งหมดจึงมีความหมายที่แตกต่างกัน
Jonathan Leffler

TTY Demystifiedมีข้อมูลย่อยง่ายเกี่ยวกับวิธีที่สัญญาณโต้ตอบกับระบบย่อย tty ของเคอร์เนล เพิ่มบริบทให้กับคำตอบของคุณ
Daniel Näslund

2
ดูเหมือนว่ารายละเอียดจะไม่แม่นยำมากนัก แต่ความเข้าใจของฉันคือ SIgint ขอให้โปรแกรมหยุดการกระทำในปัจจุบันไม่จำเป็นต้องออก สำหรับโปรแกรมที่ออกแบบมาให้ดำเนินการเพียงครั้งเดียวต่อการรันซึ่งหมายถึงการเลิกใช้งาน แต่สำหรับโปรแกรมแบบโต้ตอบที่มีลูปการอ่าน - ประเมินการพิมพ์บางประเภทอาจหมายถึงการยอมแพ้ในการประเมินปัจจุบันและกลับไปอ่านอินพุตของผู้ใช้ ฉันคิดว่าน้อยลงใน sigint
bdsl

ส่งสัญญาณอะไรระหว่างรีบูต
Dan Dascalescu

10

ดังที่ DarkDust ระบุว่าสัญญาณหลายตัวมีผลลัพธ์เหมือนกัน แต่กระบวนการต่างๆสามารถแนบการกระทำที่แตกต่างกันไปได้โดยแยกแยะวิธีสร้างสัญญาณแต่ละรายการ ดูที่ซอร์สโค้ดเคอร์เนล FreeBSD (kern_sig.c) ฉันเห็นว่าสัญญาณทั้งสองได้รับการจัดการในลักษณะเดียวกันพวกมันจะยุติกระบวนการและถูกส่งไปยังเธรดใด ๆ

SA_KILL|SA_PROC,             /* SIGINT */
SA_KILL|SA_PROC,             /* SIGTERM */

9

man 7 signal

นี่คือ manpage ที่ไม่เป็นบรรทัดฐานที่สะดวกของโครงการman-pagesของLinuxที่คุณมักต้องการดูข้อมูลสัญญาณของ Linux

เวอร์ชัน 3.22 กล่าวถึงสิ่งที่น่าสนใจเช่น:

สัญญาณ SIGKILL และ SIGSTOP ไม่สามารถจับปิดกั้นหรือเพิกเฉยได้

และมีตาราง:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process
SIGINT        2       Term    Interrupt from keyboard
SIGQUIT       3       Core    Quit from keyboard
SIGILL        4       Core    Illegal Instruction
SIGABRT       6       Core    Abort signal from abort(3)
SIGFPE        8       Core    Floating point exception
SIGKILL       9       Term    Kill signal
SIGSEGV      11       Core    Invalid memory reference
SIGPIPE      13       Term    Broken pipe: write to pipe with no
                              readers
SIGALRM      14       Term    Timer signal from alarm(2)
SIGTERM      15       Term    Termination signal
SIGUSR1   30,10,16    Term    User-defined signal 1
SIGUSR2   31,12,17    Term    User-defined signal 2
SIGCHLD   20,17,18    Ign     Child stopped or terminated
SIGCONT   19,18,25    Cont    Continue if stopped
SIGSTOP   17,19,23    Stop    Stop process
SIGTSTP   18,20,24    Stop    Stop typed at tty
SIGTTIN   21,21,26    Stop    tty input for background process
SIGTTOU   22,22,27    Stop    tty output for background process

ซึ่งสรุปสัญญาณActionที่แตกต่างเช่น SIGQUIT จาก SIGQUIT ตั้งแต่ SIGQUIT มีการดำเนินการCoreและ TermSIGINT

การดำเนินการได้รับการบันทึกไว้ในเอกสารเดียวกัน:

The entries in the "Action" column of the tables below specify the default disposition for each signal, as follows:

Term   Default action is to terminate the process.

Ign    Default action is to ignore the signal.
Core   Default action is to terminate the process and dump core (see core(5)).
Stop   Default action is to stop the process.
Cont   Default action is to continue the process if it is currently stopped.

ฉันไม่เห็นความแตกต่างระหว่าง SIGTERM และ SIGINT จากมุมมองของเคอร์เนลเนื่องจากทั้งคู่มีการดำเนินการTermและสามารถจับได้ทั้งคู่ ดูเหมือนว่าจะเป็นเพียง "ความแตกต่างของหลักการใช้งานทั่วไป":

  • SIGINT คือสิ่งที่เกิดขึ้นเมื่อคุณทำ CTRL-C จากเทอร์มินัล
  • SIGTERM เป็นสัญญาณเริ่มต้นที่ส่งโดย kill

สัญญาณบางอย่างคือ ANSI C และสัญญาณอื่น ๆ ไม่ใช่

ความแตกต่างอย่างมากคือ:

  • SIGINT และ SIGTERM เป็น ANSI C จึงพกพาได้มากกว่า
  • SIGQUIT และ SIGKILL ไม่ใช่

มีอธิบายไว้ในหัวข้อ "7.14 การจัดการสัญญาณ" ของแบบร่าง C99 N1256 :

  • SIGINT ได้รับสัญญาณความสนใจแบบโต้ตอบ
  • SIGTERM ส่งคำขอเลิกจ้างไปยังโปรแกรม

ซึ่งทำให้ SIGINT เป็นตัวเลือกที่ดีสำหรับ Ctrl + C แบบโต้ตอบ

POSIX 7

POSIX 7 เอกสารสัญญาณพร้อมsignal.hส่วนหัว: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

หน้านี้ยังมีตารางที่น่าสนใจต่อไปนี้ซึ่งกล่าวถึงบางสิ่งที่เราเคยเห็นมาแล้วman 7 signal:

Signal    Default Action   Description
SIGABRT   A                Process abort signal.
SIGALRM   T                Alarm clock.
SIGBUS    A                Access to an undefined portion of a memory object.
SIGCHLD   I                Child process terminated, stopped,
SIGCONT   C                Continue executing, if stopped.
SIGFPE    A                Erroneous arithmetic operation.
SIGHUP    T                Hangup.
SIGILL    A                Illegal instruction.
SIGINT    T                Terminal interrupt signal.
SIGKILL   T                Kill (cannot be caught or ignored).
SIGPIPE   T                Write on a pipe with no one to read it.
SIGQUIT   A                Terminal quit signal.
SIGSEGV   A                Invalid memory reference.
SIGSTOP   S                Stop executing (cannot be caught or ignored).
SIGTERM   T                Termination signal.
SIGTSTP   S                Terminal stop signal.
SIGTTIN   S                Background process attempting read.
SIGTTOU   S                Background process attempting write.
SIGUSR1   T                User-defined signal 1.
SIGUSR2   T                User-defined signal 2.
SIGTRAP   A                Trace/breakpoint trap.
SIGURG    I                High bandwidth data is available at a socket.
SIGXCPU   A                CPU time limit exceeded.
SIGXFSZ   A                File size limit exceeded.

เริ่ม BusyBox

rebootคำสั่งเริ่มต้น 1.29.2 ของ BusyBox จะส่ง SIGTERM เพื่อประมวลผลพักหนึ่งวินาทีจากนั้นส่ง SIGKILL สิ่งนี้ดูเหมือนจะเป็นเรื่องธรรมดาในโรงกลั่นต่างๆ

เมื่อคุณปิดระบบ BusyBox ด้วย:

reboot

ส่งสัญญาณไปยังกระบวนการเริ่มต้น

จากนั้นตัวจัดการสัญญาณ init จะสิ้นสุดการโทร:

static void run_shutdown_and_kill_processes(void)
{
    /* Run everything to be run at "shutdown".  This is done _prior_
     * to killing everything, in case people wish to use scripts to
     * shut things down gracefully... */
    run_actions(SHUTDOWN);

    message(L_CONSOLE | L_LOG, "The system is going down NOW!");

    /* Send signals to every process _except_ pid 1 */
    kill(-1, SIGTERM);
    message(L_CONSOLE, "Sent SIG%s to all processes", "TERM");
    sync();
    sleep(1);

    kill(-1, SIGKILL);
    message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
    sync();
    /*sleep(1); - callers take care about making a pause */
}

ซึ่งพิมพ์ไปยังเครื่องปลายทาง:

The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes

นี่คือตัวอย่างที่เป็นรูปธรรมเล็กน้อยของสิ่งนั้น

สัญญาณที่ส่งโดยเคอร์เนล


8

หลังจากที่มีการค้นหาของ Google อย่างรวดเร็วสำหรับSIGINT VS SIGTERMkillดูเหมือนว่าความแตกต่างที่มีวัตถุประสงค์เฉพาะระหว่างสองคือไม่ว่าจะถูกริเริ่มโดยแป้นพิมพ์ลัดหรือโดยการโทรที่ชัดเจนในการ

ตัวอย่างเช่นคุณสามารถสกัดกั้น sigint และทำสิ่งพิเศษกับมันได้โดยรู้ว่ามันน่าจะส่งมาจากแป้นพิมพ์ลัด อาจจะรีเฟรชหน้าจอหรืออะไรสักอย่างแทนที่จะตาย (ไม่แนะนำเนื่องจากคนคาดหวังว่า^Cจะฆ่าโปรแกรมเป็นเพียงตัวอย่าง)

ฉันยังได้เรียนรู้ว่า^\ควรส่ง sigquit ซึ่งฉันอาจจะเริ่มใช้เอง ดูมีประโยชน์มาก ๆ


3

การใช้kill(ทั้งการโทรของระบบและยูทิลิตี้ "คุณสามารถส่งสัญญาณเกือบทุกขั้นตอนไปยังกระบวนการใดก็ได้เนื่องจากคุณได้รับอนุญาตกระบวนการไม่สามารถแยกแยะได้ว่าสัญญาณมีชีวิตขึ้นมาได้อย่างไรและใครเป็นผู้ส่ง

ดังที่กล่าวไว้ SIGINT มีไว้เพื่อแยกการขัดจังหวะ Ctrl-C ในขณะที่ SIGTERM เป็นสัญญาณเทอร์มินัลทั่วไป ไม่มีแนวคิดใดที่สัญญาณจะ "มีกำลังมากกว่า" ยกเว้นเพียงอย่างเดียวคือมีสัญญาณที่ไม่สามารถปิดกั้นหรือจัดการได้ (SIGKILL และ SIGSTOP อ้างอิงจากหน้าคน)

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


0

ยกเว้นสัญญาณบางอย่างตัวจัดการสัญญาณสามารถจับสัญญาณต่างๆได้หรือพฤติกรรมเริ่มต้นเมื่อได้รับสัญญาณสามารถแก้ไขได้ ดูsignal(7)รายละเอียดในหน้าคน


ใช่ แต่ถ้าฉันไม่รู้ "ความหมาย" ของ singnal การจับสัญญาณก็ไม่มีจุดหมายเพราะฉันไม่รู้ว่าจะต้องทำอย่างไรในแอปพลิเคชันของฉัน GNU C เช่นอธิบายความแตกต่างระหว่าง SIGQUIT และ SIGTERM แต่ให้ข้อมูลเล็กน้อยเกี่ยวกับ SIGINT: gnu.org/s/libc/manual/html_node/Termination-Signals.html
Mecki

"สัญญาณSIGINT(" โปรแกรมขัดจังหวะ ") จะถูกส่งเมื่อผู้ใช้พิมพ์อักขระ INTR (โดยปกติC-c)" "SIGINT 2 Term Interrupt from keyboard" คุณกด Ctrl-C SIGINTจะถูกส่ง กระบวนการปกติจะตาย จะให้อะไรอีก
Ignacio Vazquez-Abrams

อาจมีคำอธิบายความตั้งใจที่โปรแกรมเมอร์ควรถือว่าผู้ใช้จะมีเมื่อพวกเขากด ctrl-c หมายถึงความหมายของข้อความ ดังตัวอย่างข้อมูลจำเพาะของ HTTP ทำให้ชัดเจนว่าเมื่อผู้ใช้ส่งคำขอ GET เซิร์ฟเวอร์ไม่ควรคิดว่าพวกเขาต้องการให้ทำอะไรยกเว้นส่งการตอบกลับ
bdsl
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.