Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม C

ฟังก์ชัน raise() ใน C/C++: ส่ง Signal ให้ตัวเอง

ฟังก์ชัน raise() ใช้ส่ง Signal ให้ Process ตัวเอง (Self-signal) เพื่อทดสอบ Signal Handlers หรือ Trigger การจัดการ Event ต่างๆ อยู่ใน Header <signal.h>

ไวยากรณ์

#include <signal.h>
int raise(int sig);
  • sig - Signal Number ที่จะส่ง (เช่น SIGINT, SIGTERM, SIGILL)
  • คืนค่า: 0 = สำเร็จ, Non-zero = ล้มเหลว

ตัวอย่าง: ตั้งค่า Handler และ Raise Signal

#include <signal.h>
#include <stdio.h>

// Signal Handler
void handler(int sig) {
    printf("Signal received: %d\n", sig);
}

int main() {
    // ลงทะเบียน Handler สำหรับ SIGILL (Illegal Instruction)
    signal(SIGILL, handler);
    
    printf("Sending signal: %d\n", SIGILL);
    raise(SIGILL);  // ส่ง SIGILL ให้ตัวเอง
    
    return 0;
}

ผลลัพธ์

Sending signal: 4
Signal received: 4

Common Signals (POSIX)

SignalValueคำอธิบายDefault Action
SIGHUP1Hangup (Terminal Disconnected)Terminate
SIGINT2Interrupt (Ctrl+C)Terminate
SIGQUIT3Quit (Ctrl+\\)Core Dump
SIGILL4Illegal InstructionCore Dump
SIGABRT6Abort (จาก abort())Core Dump
SIGFPE8Floating Point ExceptionCore Dump
SIGKILL9Kill (Cannot Catch/Ignore)Terminate
SIGSEGV11Segmentation ViolationCore Dump
SIGTERM15Termination RequestTerminate

signal() vs sigaction()

signal() เป็น Legacy Interface มีพฤติกรรมแตกต่างระหว่าง Systems ควรใช้ sigaction() แทน

sigaction() Example (แนะนำ)

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void handler(int sig, siginfo_t *info, void *ucontext) {
    printf("Caught signal %d\n", sig);
}

int main() {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_sigaction = handler;
    sa.sa_flags = SA_SIGINFO;
    
    sigaction(SIGUSR1, &sa, NULL);
    
    printf("PID: %d\n", getpid());
    printf("Send SIGUSR1: kill -USR1 %d\n", getpid());
    
    // Wait for signal
    pause();
    return 0;
}

การใช้งาน raise() จริง

  • Testing Signal Handlers: ทดสอบว่า Handler ทำงานถูกต้อง
  • Self-termination: raise(SIGTERM) เพื่อจบโปรแกรมอย่าง Graceful
  • Debugging: Trigger Breakpoint ผ่าน Signal
  • Inter-process Communication: ร่วมกับ fork() ส่ง Signal ให้ Child/Parent

ข้อควรระวัง

  • signal() ไม่ Reentrant-Safe - อย่าใช้ ฟังก์ชันที่ไม่ Async-Signal-Safe ใน Handler
  • Async-Signal-Safe Functions: write, _Exit, sigaction, raise ฯลฯ (ดู man 7 signal-safety)
  • printf() ใน Handler ไม่ปลอดภัย (แต่อาจทำงานได้บนบางระบบ)
  • Signal Handlers ควรสั้นที่สุด ใช้ volatile sig_atomic_t Flag แล้วจัดการใน Main Loop

สรุป

raise() ส่ง Signal ให้ตัวเอง ใช้ร่วมกับ signal() หรือ sigaction() สำหรับ Testing/Debugging ควรใช้ sigaction() แทน signal() สำหรับ Production Code