อ่าน 4 นาที
การจัดการสัญญาณ C
ใน ไลบรารีมาตรฐาน ของภาษาซีการประมวลผลสัญญาณจะกำหนดวิธีการที่โปรแกรมจัดการกับสัญญาณ ต่างๆ ขณะที่กำลังทำงาน สัญญาณอาจรายงานพฤติกรรมที่ผิดปกติภายในโปรแกรม (เช่นการหารด้วยศูนย์ )
การจัดการสัญญาณ C
| ไลบรารีมาตรฐาน C (libc) |
|---|
| หัวข้อทั่วไป |
| ส่วนหัวเบ็ดเตล็ด |
ใน ไลบรารีมาตรฐาน ของภาษาซีการประมวลผลสัญญาณจะกำหนดวิธีการที่โปรแกรมจัดการกับสัญญาณ ต่างๆ ขณะที่กำลังทำงาน สัญญาณอาจรายงานพฤติกรรมที่ผิดปกติภายในโปรแกรม (เช่นการหารด้วยศูนย์ ) หรือสัญญาณอาจรายงานเหตุการณ์แบบอะซิงโครนัสภายนอกโปรแกรม (เช่น การที่ใครบางคนกดปุ่มความสนใจแบบโต้ตอบบนแป้นพิมพ์)
สัญญาณมาตรฐาน
มาตรฐาน C กำหนดสัญญาณเพียง 6 สัญญาณเท่านั้น โดยทั้งหมดถูกกำหนดไว้ในส่วนหัว<signal.h>( <csignal>): [ 1 ]
SIGABRT– "การทำแท้ง", การยุติการคลอดที่ผิดปกติSIGFPE– ข้อผิดพลาด เกี่ยวกับเลขทศนิยมSIGILL– คำสั่งที่ "ผิดกฎหมาย" หรือไม่ถูกต้องSIGINT– "การขัดจังหวะ" คือคำขอความสนใจแบบโต้ตอบที่ส่งไปยังโปรแกรมSIGSEGV– " การละเมิดการแบ่งส่วนหน่วยความจำ " การเข้าถึงหน่วยความจำที่ไม่ถูกต้องSIGTERM– "ยุติ", ส่งคำขอการยุติไปยังโปรแกรม
อาจมีการระบุสัญญาณเพิ่มเติมใน<signal.h>ส่วนหัวโดยการใช้งาน ตัวอย่างเช่น ระบบปฏิบัติการ Unix และ ระบบปฏิบัติการ ที่คล้าย Unix (เช่นLinux ) กำหนดสัญญาณเพิ่มเติมมากกว่า 15 รายการ ดูUnix signal [ 2 ]
การดีบัก
SIGTRAPเพื่อวัตถุประสงค์ในการแก้ไขข้อผิดพลาด โปรแกรมนี้ขึ้นอยู่กับแพลตฟอร์ม และสามารถใช้งานได้บนระบบปฏิบัติการที่คล้ายUnix
การจัดการ
สามารถสร้างสัญญาณได้โดยการเรียกใช้ฟังก์ชันraise()หรือkill()การเรียกใช้ระบบ เช่นraise()ส่งสัญญาณไปยังกระบวนการปัจจุบัน หรือkill()ส่งสัญญาณไปยังกระบวนการที่ระบุ
ตัวจัดการสัญญาณคือฟังก์ชันที่ถูกเรียกโดยสภาพแวดล้อมเป้าหมายเมื่อเกิดสัญญาณที่เกี่ยวข้อง สภาพแวดล้อมเป้าหมายจะระงับการทำงานของโปรแกรมจนกว่าตัวจัดการสัญญาณจะส่งค่ากลับหรือเรียกใช้ฟังก์ชันlongjmp()อื่น
ตัวจัดการสัญญาณสามารถตั้งค่าได้ด้วยsignal()หรือsigaction()พฤติกรรมของ ได้signal()ถูกเปลี่ยนแปลงหลายครั้งตลอดประวัติศาสตร์ และไม่แนะนำให้ใช้[ 3 ]สามารถใช้งานได้เฉพาะเมื่อใช้เพื่อตั้งค่าการจัดการสัญญาณเป็น SIG_DFL หรือ SIG_IGN เท่านั้น ตัวจัดการสัญญาณสามารถระบุได้สำหรับสัญญาณทั้งหมด ยกเว้นสองสัญญาณ ( ไม่สามารถดักจับ บล็อก หรือเพิกเฉยต่อ SIGKILLและSIGSTOPได้)
หากสัญญาณรายงานข้อผิดพลาดภายในโปรแกรม (และสัญญาณนั้นไม่ใช่แบบอะซิงโครนัส) ตัวจัดการสัญญาณสามารถยุติการทำงานได้โดยการเรียกใช้เมธอดabort(), exit(), longjmp()หรือ
ฟังก์ชัน
| การทำงาน | คำอธิบาย |
|---|---|
raise | ส่งสัญญาณไปยังกระบวนการเรียกอย่างไม่เป็นธรรมชาติ |
kill | ส่งสัญญาณไปยังกระบวนการที่กำหนดไว้โดยเทียม |
signal | กำหนดการกระทำที่จะเกิดขึ้นเมื่อโปรแกรมได้รับสัญญาณเฉพาะ |
ตัวอย่างการใช้งาน
#include <signal.h> #include <stdio.h> #include <stdlib.h>สถานะsig_atomic_t ที่ผันผวน= 0 ;static void catch_function ( int signo ) { status = signo ; }int main ( void ) { // ตั้งค่าฟังก์ชันด้านบนเป็นตัวจัดการสัญญาณสำหรับสัญญาณ SIGINT: if ( signal ( SIGINT , catch_function ) == SIG_ERR ) { fprintf ( stderr , "เกิดข้อผิดพลาดขณะตั้งค่าตัวจัดการสัญญาณ\n " ); return EXIT_FAILURE ; } printf ( "กำลังยกสัญญาณความสนใจแบบโต้ตอบ" ); if ( raise ( SIGINT )) { fprintf ( stderr , "เกิดข้อผิดพลาดในการยกสัญญาณ\n " ); return EXIT_FAILURE ; } if ( status == SIGINT ) { printf ( "จับสัญญาณความสนใจแบบโต้ตอบได้แล้ว" ); } printf ( "กำลังออกจากโปรแกรม" ); return EXIT_SUCCESS ; // ออกจากโปรแกรมหลังจากยกสัญญาณ}ภาษาอื่นๆ
ซี++
โดยทั่วไปแล้ว สัญญาณในภาษา C จะถูกใช้งานใน C++ ในลักษณะเดียวกับในภาษา C อย่างไรก็ตาม เรายังสามารถเขียนฟังก์ชันห่อหุ้มสำหรับการใช้งาน ในรูปแบบ RAII ได้อีกด้วย
ส่งออกโมดูลวิกิพีเดียตัวอย่าง;import < csignal > ; // จำเป็นสำหรับการได้มาซึ่งมาโครimport std ;โดยใช้std :: function ;ส่งออกเนมสเปซวิกิพีเดีย:: examples {คลาสSignal { private : using Handler = function < void ( int ) > ; int sig ; public : static constexpr int ABRT = SIGABRT ; static constexpr int FPE = SIGFPE ; static constexpr int ILL = SIGILL ; static constexpr int INT = SIGINT ; static constexpr int SEGV = SIGSEGV ; static constexpr int TERM = SIGTERM ; static constexpr int DFL = SIGDFL ; static constexpr int IGN = SIGIGN ; static constexpr int ERR = SIGERR ;สัญญาณที่ชัดเจน( int sig ) : sig { sig } {}[[ nodiscard ]] int getSignal () const noexcept { return sig ; }ตัวจัดการตัวจัดการ( ตัวจัดการตัวจัดการ) const noยกเว้น{ return std :: สัญญาณ( sig ตัวจัดการ) ; }int raise () const noexcept { return std :: raise ( sig ); } };}นอกจากนี้ยังสามารถทำได้ด้วยBoostboost::asio::signal_set โดย ใช้ คลาส
ซี#
สัญญาณ C สามารถใช้ร่วมกับP/InvokeและMono.Unix.Native.Syscall.
ชวา
สัญญาณ C สามารถใช้งานได้อย่างไม่เป็นทางการในภาษาJava จาก โมดูลjdk.unsupportedโดยใช้คลาส JVM ภายในsun.misc.Signalและอินเทอร์เฟsun.misc.SignalHandlerซ[ 4 ]
แพ็คเกจorg.wikipedia.example ;import sun.misc.Signal ; import sun.misc.SignalHandler ;public class Example { public static void main ( String [] args ) { SignalHandler handler = new SignalHandler () { public void handle ( Signal sig ) { boolean handled = handlers . get ( type ). handle ( type ); if ( ! handled ) { if ( type . getDefaultAction () == SignalType . DefaultAction . IGNORE ) { SignalHandler . SIG_IGN . handle ( sig ); } else { SignalHandler . SIG_DFL . handle ( sig ); } } } }; Signal . handle ( new Signal ( "INT" ), handler ); } }สนิม
สามารถใช้สัญญาณร่วมกับ crate signal_hookใน Rust ได้[ 5 ]
ใช้std :: process ; ใช้std :: thread ; ใช้std :: time :: Duration ;ใช้signal_hook :: consts :: signal :: * ; ใช้signal_hook :: iterator :: Signals ;fn main () { let mut signals : Signals = Signals :: new ( & [ SIGINT , SIGTERM ]). expect ( "Failed to set up signal handling" );thread :: spawn ( move || { for signal in signals.forever ( ) { match signal { SIGINT => { println! ( "ได้รับ SIGINT (Ctrl+C) ออกจากโปรแกรมอย่างราบรื่น" ) ; process :: exit ( 0 ); } SIGTERM => { println! ( "ได้รับ SIGTERM ออกจากโปรแกรมอย่างราบรื่น" ); process :: exit ( 0 ); } _ => unreachable! (), } } });loop { println! ( "กำลังทำงาน..." ); thread :: sleep ( Duration :: from_secs ( 2 )); } }ดูเพิ่มเติม
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ การจัดการสัญญาณ C
ใน ไลบรารีมาตรฐาน ของภาษาซีการประมวลผลสัญญาณจะกำหนดวิธีการที่โปรแกรมจัดการกับสัญญาณ ต่างๆ ขณะที่กำลังทำงาน สัญญาณอาจรายงานพฤติกรรมที่ผิดปกติภายในโปรแกรม (เช่นการหารด้วยศูนย์ )
สัญญาณมาตรฐาน
มาตรฐาน C กำหนดสัญญาณเพียง 6 สัญญาณเท่านั้น โดยทั้งหมดถูกกำหนดไว้ในส่วนหัว ( ): [ 1 ]
การดีบัก
SIGTRAP เพื่อวัตถุประสงค์ในการแก้ไขข้อผิดพลาด โปรแกรมนี้ขึ้นอยู่กับแพลตฟอร์ม และสามารถใช้งานได้บนระบบปฏิบัติการที่คล้าย Unix
การจัดการ
สามารถสร้างสัญญาณได้โดยการเรียกใช้ฟังก์ชัน raise() หรือ kill() การเรียกใช้ระบบ เช่น raise() ส่งสัญญาณไปยังกระบวนการปัจจุบัน หรือ kill() ส่งสัญญาณไปยังกระบวนการที่ระบุ