23.08.05 최초 작성
23.11.14 sigaction, 타이머 추가
비동기적 이벤트를 핸들링하기 위한 메커니즘을 제어하기 위한 Software Interrupt
신호처리의 순서
발생 (Raise) : 프로그램에서 발생한 예외적인 상황에서 발생. 프로세스나 kernel에서 생성 or 전달.보관 (Store) : 신호 전달 전 까지 kernel이 보관. 전달 가능해지면 해당 프로세스에게 전달.처리 (Handling) : 지정된 방법에 따라 신호 처리. 수행하던 프로세스를 중단하고 지정한 방식(Signal Handler)으로 작업을 수행.Pending Signal : 아직 처리되지 않은 신호
Linux에서 신호의 종류


Signal Handler : 특정 신호를 처리하기 위해 지정된 함수. SIGKILL, SIGSTOP을 제외하고 수정 가능함.
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
///
signum : 처리할 신호 번호
handler : Signal Handler의 함수 포인터 (SIG_IGN : 신호 무시, SIG_DFL : default handler로 처리)
Return : 기존 handler의 함수 포인터
(SIG_ERR : Error)
#include <signal.h>
void psignal(int sig, const char *msg);
///
sig : 신호 id
msg : 설명 앞에 출력할 메시지
#include <string.h>
char* strsignal(int sig);
///
sig : 신호
Return : sig에 대한 신호 설명을 문자열로 반환
#include <signal.h>
extern const char *const sys_siglist[];
///
전역 변수를 extern으로 가져와서 사용 가능
sigaction : 특정 신호에 관련된 동작을 조회/수정할 수 있는 함수#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
///
signum : 시그널 번호를 의미합니다. (SIGKILL과 SIGSTOP 불가)
act : signum에 대해 동작할 함수
oldact : 시그널에 대한 동작을 조회하는 정보입니다.
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
fork()Signal 처리 방식 상속 받음Pending Signal은 상속 받지 못함exec()Signal Handler 상속 받지 않음Pending Signal 상속 받음#include <sys/types.h>
#include <signal.h>
int kill(pit_t pid, int signo);
///
pid : 신호를 보낼 대상(0 : 자신이 속한 Process Group 내 모든 프로세스, -1 : 현재 프로세스가 가진 권한으로 신호를 보낼 수 있는 모든 프로세스, < -1 : GID == (-pid)인 Process Group)
signo : 보낼 신호 번호
Return
(0 : Success, -1 : Fail)
#include <signal.h>
int raise(int sig); //자신에게 신호 전송
///
sig : 전송할 신호
Return
(0 : Success, Otherwise : Fail)
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
///
seconds : 시간 지정(초)
Return : SIGALRM 발생
필요 권한전송자의 RUID or EUID = 수신자의 RUID or EUIDRoot는 모든 프로세스에게 전달 가능Null signal(=0)을 활용해 권한 확인 가능Critical Region 보호를 위해 신호를 차단sigset_t : 각 bit가 신호 번호와 1대1 대응 됨#include <signal.h>
int sigemptyset(sigset_t *set); //set 비우기
int sigfillset(sigset_t *set); // set을 다 채우기
int sigaddset(sigset_t *set, int signum); // 신호 set에 추가
int sigdelset(sigset_t *set, int signum); // 신호 set에서 삭제
int sigismember(const sigset_t *set, int signum); // Return 1 : set에 해당 신호 존재
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
///
how : 지정 방법
(SIG_SETMASK : set을 blocking mask로 적용
SIG_BLOCK : blocking 대상 추가
SIG_UNBLOCK : blocking 대상에서 제거)
set : 적용할 signal set
(NULL : how를 무시, 현재 signal mask 유지)
oldset : 적용 전 signal set 저장
Return
(0 : Sucess, -1 : Fail)
Pending Signal들은 blocking이 풀리면 전달 됨
#include <signal.h>
int sigsuspend(const sigset_t *mask); // Signal Mask를 임시 교체 후 block되지 않은 signal이 도착할 때 까지 대기
Return
(항상 -1, errno = EINTR : 신호에 의해 interrupt 발생)
타이머 시그널 핸들러 호출setitimer : 설정한 시간마다 event 발생하도록 설정#include <sys/time.h>
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
///
which : timer type
value : 설정할 시간 간격 값
oval : 현재의 시간 간격 값
Return
(0 : Sucess, -1 : Fail)
| which | ITMER_REAL | ITIMER_VIRTURE | ITIMER_PROF |
|---|---|---|---|
| 의미 | 실제 시간 기준 | user mode 시간 기준 | user / kernel mode 시간 기준 |
getitimer : 현재 설정된 시간 간격 확인#include <sys/time.h>
int getitimer(int which, struct itimerval *curr_value);
Return
(0 : Sucess, -1 : Fail)
sleep : 일정 시간동안 작업 중지#include <unistd.h>
unsigned int sleep(unsigned int seconds);
Return
(0 : Sucess, unsinged int : 일찍 sleep이 끝났을 때 sleep하지 않은 시간 표시)
setitimer의 단점을 보완하고자 사용하는 방식RTOS같은 실시간 사용을 보장해야하는 상황에서 사용timer_create : 타이머 생성#define _POSIX_C_SOURcE_199309
#include <signal.h>
#include <time.h>
int timer_create(clockid_t clockid, sturct sigevent *evp, timer_t *timerid);
///
clockid : 어떤 타이머를 사용할지 입력
evp : 타이머가 만료될 때 호출자가 알림받는 방법을 나타냄
timeid : 생성된 timeid 저장하는 공간
Return
(0 : Sucess, -1 : error)
| clockid | CLOCK_REALTIME | CLOCK_VIRTUAL | CLOCK_PROF |
|---|---|---|---|
| 의미 | 실제 시간 기준 | user mode 시간 기준 | user / kernel mode 시간 기준 |
nanosleep : 일정 시간동안 작업 중지 시키는 함수로 sleep보다 고해상도의 기능을 지원함#define _POSIX_C_SOURCE 199309
#include <time.h>
int nanosleep(const struct timespec *request, struct timespec *remain);
request.tv_sec = 1;
request.tv_nsec = 123; //멈추는 시간 1.123초
///
request : 멈추고 싶은 시간을 저장하는 구조체
remain : request에 저장된 시간 - 실제 멈췄던 시간 저장하는 공간
Return
(0 : Sucess, -1 : error / sleep이 중단되었을 때)
| timespec 구조체 | tv_sec | tv_nsec |
|---|---|---|
| 의미 | 멈추고 싶은 시간의 (sec) | 멈추고 싶은 시간의 소숫점 아래 숫자 |
timer_settime, timer_gettime : POSIX 버전 setitimer, getitimer#include <time.h>
int timer_settime(timer_t timerid, int flags,
const struct itimerspec *restrict new_value,
struct itimerspec *restrict old_value);
int timer_gettime(timer_t timerid, struct itimerspec *curr_value);
///
timerid : 조작하고자 하는 timer를 나타내는 timer_t 인자
flags : 타이머 설정
new_value : 설정하고자 하는 시간 간격
old_value : 이전에 설정했던 값
curr_value : 확인하고자 하는 간격 값을 저장
Return
(0 : Success, -1 : Fail)