티스토리 뷰
728x90
반응형
리눅스 C++ Signal 핸들러 클래스 (멀티스레드 기반)
1. 개요
이 문서는 리눅스 환경에서 시그널 처리 전용 클래스를 만들고, 별도의 스레드에서 안전하게 시그널을 처리하는 구조를 설명합니다.
2. 핵심 설계
- 시그널과 콜백을 등록하는 유연한 클래스 구조
- 핸들링은 별도 스레드에서
sigwaitinfo()
로 처리 - 메인 스레드는 자유롭게 동작 가능
3. 클래스 헤더: SignalHandler.hpp
#pragma once
#include <functional>
#include <map>
#include <thread>
#include <atomic>
#include <csignal>
#include <set>
class SignalHandler {
public:
using Callback = std::function<void(int, siginfo_t*)>;
SignalHandler();
~SignalHandler();
bool registerSignal(int signal, Callback cb);
void start();
void stop();
private:
void signalThreadFunc();
std::map<int, Callback> _callbacks;
std::set<int> _registeredSignals;
std::thread _signalThread;
std::atomic<bool> _running;
};
4. 클래스 구현: SignalHandler.cpp
#include "SignalHandler.hpp"
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <pthread.h>
SignalHandler::SignalHandler()
: _running(false) {}
SignalHandler::~SignalHandler() {
stop();
}
bool SignalHandler::registerSignal(int signal, Callback cb) {
_callbacks[signal] = cb;
_registeredSignals.insert(signal);
return true;
}
void SignalHandler::start() {
if (_running) return;
_running = true;
sigset_t signalSet;
sigemptyset(&signalSet);
for (int sig : _registeredSignals) {
sigaddset(&signalSet, sig);
}
if (pthread_sigmask(SIG_BLOCK, &signalSet, nullptr) != 0) {
perror("pthread_sigmask");
return;
}
_signalThread = std::thread(&nxcSignalHandler::signalThreadFunc, this);
}
void SignalHandler::stop() {
if (!_running) return;
_running = false;
pthread_kill(_signalThread.native_handle(), SIGINT);
if (_signalThread.joinable()) {
_signalThread.join();
}
}
void SignalHandler::signalThreadFunc() {
sigset_t signalSet;
sigemptyset(&signalSet);
for (int sig : _registeredSignals) {
sigaddset(&signalSet, sig);
}
while (_running) {
siginfo_t info;
int sig = sigwaitinfo(&signalSet, &info);
if (sig > 0) {
auto it = _callbacks.find(sig);
if (it != _callbacks.end()) {
it->second(sig, &info);
} else {
std::cerr << "[nxcSignalHandler] No handler for signal: " << sig << std::endl;
}
}
}
}
5. 사용 예시: main.cpp
#include "SignalHandler.hpp"
#include <iostream>
#include <unistd.h>
int main() {
std::cout << "[Main] PID: " << getpid() << std::endl;
SignalHandler handler;
handler.registerSignal(SIGUSR1, [](int sig, siginfo_t* info) {
std::cout << "[Handler] Received SIGUSR1 from PID: " << info->si_pid << std::endl;
});
handler.registerSignal(SIGINT, [](int, siginfo_t*) {
std::cout << "[Handler] SIGINT received. Exiting." << std::endl;
exit(0);
});
handler.start();
while (true) {
std::cout << "[Main] Working..." << std::endl;
sleep(2);
}
return 0;
}
6. 빌드 명령
g++ -std=c++17 -pthread -o app main.cpp nxcSignalHandler.cpp
7. 장점 요약
- 별도 스레드에서 안전하게 시그널 처리
- 메인 스레드와 격리된 구조
- 콜백 방식으로 유연한 시그널 관리
💡 확장 아이디어:
- SIGCHLD, SIGTERM 등도 등록 가능
- 콜백에서 작업 큐와 연동하여 비동기 처리 가능
- sigqueue()로 사용자 데이터 수신 처리 추가 가능
728x90
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 블루버블
- PowerShell
- 성산블루버블
- 울릉도
- C#.NET
- 스쿠버다이빙
- OpenSource
- 블루버블다이브팀
- DLL
- 블루버블다이빙팀
- 스쿠버 다이빙
- 서귀포
- Build
- 윈도우
- 외돌개
- C# 고급 기술
- C#
- 현포다이브
- Thread
- CMake
- 서귀포블루버블
- 패턴
- 암호화
- 리눅스
- 제주도
- ip
- Windows
- C++
- Linux
- C
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함
반응형