C++에서 SIGABRT 신호 처리
이 기사에서는 C++에서SIGABRT
신호를 처리하는 방법에 대한 여러 방법을 보여줍니다.
sigaction
을 사용하여SIGABRT
신호 핸들러 등록
Unix 기반 운영 체제는 한 프로그램이 다른 프로그램에 비동기 적으로 메시지를 보낼 수있는 메커니즘 인 신호라는 기능을 지원합니다. 신호는 일반적으로 프로그램을 중단해야하는 사용자 또는 운영 체제 프로세스에서 전송됩니다. 시그널 핸들러는 프로그램이 주어진 시그널을 받으면 호출되는 코드 섹션입니다. 프로그램 중단, 프로그램 중지 및 해당 기본 신호 처리기로 프로그램 계속과 같은 작업에 대한 몇 가지 표준 신호가 있습니다. 그러나 사용자는 이러한 신호 처리기 대부분을 사용자 정의 함수로 재정의 할 수 있으며 sigaction
은이를 등록하는 함수입니다.
SIGABRT
는 기본적으로 프로그램이 종료되는 신호 중 하나입니다. 다음 코드 예제에서는 신호 핸들러를 재정의하고 신호가 수신되면 호출 할 정의 된 함수 (cleanupRoutine
)를 할당합니다.
처음에struct sigaction
유형 객체는memset
함수 호출로 선언하고 초기화해야합니다.
다음으로 데이터 멤버 sa_handler
에 호출해야하는 함수의 주소를 할당해야합니다.
그런 다음 SIGABRT
핸들러를 방해하지 않도록 다른 신호를 마스킹해야하며 sigfillset
함수 호출이이를 달성합니다.
마지막으로, 신호 번호,struct sigaction
의 주소, 이전 작업을 저장할 수있는 선택적 구조체의 세 가지 인수를 사용하는sigaction
호출로 신호 핸들러를 등록합니다.
이 경우 세 번째 인수를 무시하지만 nullptr
을 매개 변수로 지정해야합니다. 문자열을 콘솔에 출력 한 다음 프로그램을 종료하여 핸들러의 올바른 실행을 쉽게 확인할 수 있도록cleanupRoutine
함수를 정의했습니다. 나머지 프로그램은 사용자가 SIGABRT
신호를 보낼 때 중단되어야하는 무한 루프입니다. 프로그램을 테스트하려면 하나의 터미널 창에서 실행하고 다음 명령 kill -SIGABRT pid_num_of_program
을 실행하여 두 번째 창에서 신호를 보냅니다.
#include <csignal>
#include <cstring>
#include <iostream>
void cleanupRoutine(int signal_number) {
write(2, "printed from cleanupRoutine\n", 28);
_exit(EXIT_SUCCESS);
}
int main() {
struct sigaction sigabrt_action {};
memset(&sigabrt_action, 0, sizeof(sigabrt_action));
sigabrt_action.sa_handler = &cleanupRoutine;
if (sigfillset(&sigabrt_action.sa_mask) != 0) {
perror("sigfillset");
exit(EXIT_FAILURE);
}
if (sigaction(SIGABRT, &sigabrt_action, nullptr) != 0) {
perror("sigaction SIGABRT");
exit(EXIT_FAILURE);
}
int i = 0;
while (true) {
i += 1;
}
exit(EXIT_SUCCESS);
}
신호 처리기에서sig_atomic_t
변수 사용
신호 처리기는 특정 기능을 갖는 데 필요한 특수한 유형의 함수입니다. 즉, 올바르게 작동 할 수있는 유일한 변수는 원자 변수입니다. 신호 처리기 실행 중에 설정할 수있는 정수인 특수 유형 sig_atomic_t
가 있습니다. 이 변수는volatile
키워드로 선언되며 모든 수정 사항은 전역 적으로 표시됩니다. 다음 예제는 루프 문에이 변수를 조건으로 포함하는 방법을 보여줍니다.
핸들러는 변수를 1에서 0으로 만 설정하고 신호가 수신되면 프로그램을 종료하지 않습니다. 즉, 프로그램은 중단 된 지점부터 계속하려고합니다. 이 경우 루프 반복이 다시 시작되고 조건이 거짓으로 확인되면 루프에서 점프합니다. 이러한 방식으로 사용자는 신호를 사용하여 프로그램 동작을 제어 할 수 있습니다.
#include <csignal>
#include <cstring>
#include <iostream>
using std::cout;
using std::endl;
volatile sig_atomic_t shutdown_flag = 1;
void cleanupRoutine(int signal_number) { shutdown_flag = 0; }
int main() {
struct sigaction sigabrt_action {};
memset(&sigabrt_action, 0, sizeof(sigabrt_action));
sigabrt_action.sa_handler = &cleanupRoutine;
if (sigfillset(&sigabrt_action.sa_mask) != 0) {
perror("sigfillset");
exit(EXIT_FAILURE);
}
if (sigaction(SIGABRT, &sigabrt_action, nullptr) != 0) {
perror("sigaction SIGABRT");
exit(EXIT_FAILURE);
}
int i = 0;
while (shutdown_flag) {
i += 1;
}
cout << "Exiting ..." << endl;
exit(EXIT_SUCCESS);
}
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook