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

การจัดการสัญญาณ (Signal Handling) ใน C++

สัญญาณ (Signals) คือการขัดจังหวะที่ส่งมายังโปรเซสโดยระบบปฏิบัติการ ซึ่งสามารถทำให้โปรแกรมจบก่อนเวลา สร้าง interrupt ได้โดยกด Ctrl+C บน UNIX, LINUX, Mac OS X หรือ Windows

มีสัญญาณที่โปรแกรมจับไม่ได้ แต่มีรายการสัญญาณต่อไปนี้ที่จับได้ในโปรแกรมและดำเนินการตามสัญญาณ สัญญาณเหล่านี้กำหนดใน header file ของ C++

Signal Description
SIGABRTการจบโปรแกรมแบบผิดปกติ เช่น เรียก abort
SIGFPEการดำเนินการคณิตศาสตร์ผิดพลาด เช่น หารศูนย์ หรือ overflow
SIGILLตรวจพบคำสั่งผิดกฎหมาย
SIGINTได้รับสัญญาณสนใจแบบโต้ตอบ (เช่น Ctrl+C)
SIGSEGVการเข้าถึงหน่วยความจำไม่ถูกต้อง
SIGTERMคำขอจบโปรแกรมที่ส่งมายังโปรแกรม

ฟังก์ชัน signal()

ไลบรารีจัดการสัญญาณ C++ มีฟังก์ชัน signal เพื่อจับเหตุการณ์ไม่คาดคิด ไวยากรณ์:

void (*signal (int sig, void (*func)(int)))(int);

อย่างง่าย ฟังก์ชันนี้รับสองอาร์กิวเมนต์: อาร์กิวเมนต์แรกเป็น integer แทนหมายเลขสัญญาณ อาร์กิวเมนต์ที่สองเป็น pointer ไปยังฟังก์ชันจัดการสัญญาณ

ตัวอย่างจับสัญญาณ SIGINT ด้วย signal()

ตัวอย่าง

#include <iostream>
#include <csignal>
using namespace std;

void signalHandler(int signum) {
  cout << "Interrupt signal (" << signum << ") received.\n";
  // cleanup and close up stuff here
  exit(signum);
}

int main() {
  // ลงทะเบียนสัญญาณ SIGINT และ handler
  signal(SIGINT, signalHandler);
  while (1) {
    cout << "Going to sleep...." << endl;
    sleep(1);
  }
  return 0;
}

ผลลัพธ์

Going to sleep....
Going to sleep....
Going to sleep....

หลังกด Ctrl + C จะแสดง:

ผลลัพธ์

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.

ฟังก์ชัน raise()

สร้างสัญญาณได้ด้วย raise() ซึ่งรับหมายเลขสัญญาณ integer ไวยากรณ์:

int raise (signal sig);

sig คือหมายเลขสัญญาณ: SIGINT, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGTERM, SIGHUP ตัวอย่างสร้างสัญญาณภายในด้วย raise()

ตัวอย่าง

#include <iostream>
#include <csignal>
using namespace std;

void signalHandler(int signum) {
  cout << "Interrupt signal (" << signum << ") received.\n";
  exit(signum);
}

int main() {
  int i = 0;
  signal(SIGINT, signalHandler);
  while (++i) {
    cout << "Going to sleep...." << endl;
    if (i == 3) {
      raise(SIGINT);
    }
    sleep(1);
  }
  return 0;
}

ผลลัพธ์

Going to sleep....
Going to sleep....
Going to sleep....
Interrupt signal (2) received.