본문 바로가기

Computer Science/시스템프로그래밍2

시그널(signal)

-시그널

: 유닉스에서 30년 이상 사용된 전통적인 기법

: 커널 또는 프로세스에서 다른 프로세스에 어떤 이벤트가 발생되었는지를 알려주는 기법

 

ex) CTRL+C : 눌러서 프로세스 종료시키기, CTRL+Z : 눌러서 해당 프로세스가 백그라운 프로세스로 바꾸기

-> 미리 정의 되어있는 시그널이 운영체제에서 프로세스에 전달이 되는 것 ,그래서 프로세스에서 해당 시그널에 알맞은 디폴트 처리되어 있는 것으로 동작한다. 

 

시그널 종류 (시그널 번호가 매핑)

- SIGKILL : 프로세스 죽이기 (슈퍼관리자가 사용하는 시그널)

- SIGALARM : 알람 발생

- SIGSTP : 프로세스 멈추기 (ctrl + z)

- SIGCONT : 멈춰진 프로세스 실행하기

- SIGINT : 프로세스에 인터럽트를 보내서 프로세스 죽이기 (ctrl+c)

- SIGSEGV : 프로세스가 다른 메모리 영역을 침범했을 때

 

kill -l (이름과 함께 시그널 번호가 지정된 것 확인 가능)

 

시그널 동작

: 프로그램에서 특정 시그널의 기본 동작 대신 다른 동작을 하도록 구현이 가능

: 각 프로세스에서 시그널 처리에 대해 다음과 같은 동작 설정 가능

1. 시그널 무시

2. 시그널 블록 (블록을 푸는 순간, 해당 프로세스에서 시그널 처리)

3. 프로그램 안에 등록된 시그널 핸들러로 재정의한 특정 동작 수행

4. 등록된 시그널 핸들러가 없다면, 커널에서 기본 동작 수행

 

- 시그널 보내기 (해당 프로세스에 특정 시그널을 보낼 때 사용)

int kill (pid_t pid, int sig);

pid : 프로세스 pid, sig : 시그널 번호

 

- 받은 시그널에 따른 동작 정의

void (*signal(int signum, void (*handler)(int)))(int);

ex)

signal(SIGINT,SIG_IGN);

SIGINT : 시그널 수신 시, SIG_IGN : 시그널 무시 (디폴트 동작)

signal(SIGINT,(void *)signal_handler);

SIGINT : 시그널 수신 시, 프로그램안에서 정의한 signal_handler함수를 호출

 

실습 1

signal.c 코드 작성하고 백그라운드에서 실행

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

static void signal_handler(int signo){
	printf("Catch SIGINT!, but no stop!\n");
}

int main(void){
	if(signal(SIGINT,signal_handler)==SIG_ERR){
		printf("Can't catch SIGINT!\n");
		exit(1);
	}
	for(;;)
		pause();
	return 0;
}

 

실습2.

sigkill.c에서 시그널을 내가 재정의 하여 실행

#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv){
	int pid, result;
	int sig_num;
	if (argc !=3){
		printf("usage %s [pid] [signum]\n",argv[0]);
		exit(1);
	}
	pid=atoi(argv[1]);
	sig_num=atoi(argv[2]);
	result=kill(pid,sig_num);
	if (result<0){
		perror("To send Signal is failed\n");
		exit(1);
	}
	return 0;
}