본문 바로가기
컴퓨터공학기초 개념/시스템 프로그래밍

28. 시그널 - 사용법 이해

by devraphy 2021. 9. 21.

0. 시작하기전에

- 운영체제 파트에서 시그널을 IPC기법으로 사용할 수 있다는 것을 배웠다. 

- 프로세스에서 발생한 이벤트를 조건으로 인터럽트를 발생시켜 다른 프로세스가 알게 하는 방식이었다. 

 

https://devraphy.tistory.com/175

 

22. 프로세스 - IPC 기법(signal, socket)

- IPC 기법이란, 컴퓨터 구조적으로 불가능한 커뮤니케이션 간의 소통을 가능하게 하는 일종의 우회방법이다. - 다양한 IPC 기법이 존재하지만, 가장 많이 사용하고 있는 signal과 socket이 있다. - 사

devraphy.tistory.com

 

- 하지만, 이 시그널을 단순히 IPC기법 중 하나로 설명하기에는 그 역할이 너무 방대하다. 

- 그러므로 시그널에 대해서 알아보자. 


1. 시그널(signal)이란?

- UNIX에서 30년 이상 사용된 전통적인 기법

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

   ex) 터미널에서 Ctrl + C를 눌러 프로세스를 종료시키는 것 = 시그널 사용 

 

 

a) 시그널의 기본 동작 

- OS에는 다양한 시그널이 default로 정의되어 있다. 

- 간단한 예를 통해서 시그널의 동작과정을 이해해보자. 

- 터미널에서 Ctrl + C를 누르면,  OS에서 이를 시그널로 인식한다. 

- OS는 시그널에 해당하는 기능을 찾고, 시그널이 발생된 프로세스에서 해당 기능을 실행한다. 

- 즉, 프로세스는 종료된다. 

 

 

b) kill -l 

- 운영체제에는 기본적으로 정의된 시그널이 존재한다. 

- 이를 확인하기 위해서는 다음의 명령어 kill -l을 통해서 확인할 수 있다.

주요 시그널의 의미

 


2. 시그널 재정의

- 프로그램에서 특정 시그널의 기본 동작 대신 다른 동작을 구현할 수 있는데, 이를 재정의라고 한다. 

- 각 프로세스에서 다음과 같은 동작을 구현할 수 있다.

 

▶ 시그널 무시

▶ 시그널 블락(블락을 푸는 순간, 해당 프로세스에서 시그널을 수행한다.)

▶ 프로그램 내부에 등록된 시그널 핸들러를 통해 재정의한 동작 수행

▶ 커널에서 기본(default) 동작 수행  

 

a) 시그널 동작 정의 

- 아래의 예시는 시그널 무시와 시그널 핸들러를 호출하는 방식으로 시그널 동작을 처리한 것이다. 

- 다음의 예시를 살펴보자. 

#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);

// 예시 1
// void (*handler)(int): SIG_IGN - 시그널 무시 / SIG_DFL - 시그널 디폴트
signal(SIGINT, SIG_IGN); // 특정한 시그널 번호가 발동하면 무시한다. 

// 예시 2
// SIGINT 시그널 수신 시, signal_handler 함수를 호출
signal(SIGINT, (void *)signal_handler); // 특정 시그널 번호가 발동하면 시그널 핸들러 호출

 

 

b) 시그널 예시

1. sigloop.c

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

static void signal_hander(int signo) { // 시그널 핸들러 정의 
        printf("Catch SIGINT!, but no stop\n");
}

int main(void) {
        if (signal(SIGINT, signal_hander) == SIG_ERR) { // 핸들러 에러처리
                printf("Can't catch SIGINT! \n");
                exit(1);
        }
        for (;;) // 무한루프 
                pause();
        return 0;
}

- 위의 프로그램은 SIGINT를 재정의한 프로그램이다.

- SIGINT는 터미널에서 Ctrl + C를 눌렀을 때, 동작하는 시그널로 프로세스를 종료하는 시그널이다. 

- SIGINT가 발동되면, 기본동작을 수행하지 않고 signal_handler라는 함수가 동작하도록 재정의 하였다.

- 무한루프를 도는 프로그램이므로, 백그라운드에서 실행하도록 한다. 

 

- 백그라운드에서 잘 실행되고 있는 것을 확인할 수 있다. 

- sigloop의 프로세스 번호가 14219번 이라는 것을 확인하였다. 

 

 

 

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;
}

- 위의 프로그램은 pid와 signum을 인자로 받아서 kill 시그널에게 넘기도록 하는 프로그램이다. 

- 만약 kill 시그널이 제대로 작동하지 않는다면, 위에서 정의한 에러메세지가 출력될 것이다. 

- sigloop를 백그라운드에서 실행시켜놓은 상태에서 다음과 같이 터미널에 입력해보자. 

 

- 앞쪽 숫자는 PID이고 뒤에 2는 SIGINT의 signal 번호를 의미한다. 

- 올바른 PID와 시그널 번호가 sigkill 프로그램에게 전달되면, 이는 kill 메소드를 호출한다. 

- kill 메소드는 프로세스를 중단시키기 위해 SIGINT 시그널을 호출하게 된다.

- SIGINT 시그널을 호출하게 되면, 위에서 재정의한 동작이 시그널 핸들러가 작동한다. 

 

 

- 전체적인 과정은 다음과 같다. 

- 이처럼 시그널을 재정의하여, 시그널이 default 동작이 아닌 재정의된 동작을 수행하도록 할 수 있다.

 


3. 시그널과 프로세스 

- 다음 그림을 통해 시그널이 프로세스 내부적으로 어떻게 동작하는지 알아보자. 

- 프로세스 내부에 프로세스의 상태를 나타내는 PCB에는 시그널을 처리하기위한 몇가지 자료구조가 있다.

* PCB(Process Control Block) 

 

▶ pending

   - 수신된 시그널을 순서대로 대기시켜놓는 자료구조 (FIFO 순서)

 

▶ sigpending

   - blocked와 함께 관리되는 자료구조 

 

▶ blocked

   - 64 비트로 이루어진 자료구조

   - 운영체제의 기본 64개의 시그널을 표시한다. 

   - blocked에 표시된 시그널은 시그널 블락에 상태가 된다.

 

▶ sig

   - 각 시그널에 대해 어떤 동작을 처리해야하는지를 관리한다.

   - 시그널의 default 동작인지, 재정의 동작인지를 처리한다. 

 

a) 결론

- 이처럼 프로세스는 시그널 뿐만 아니라 시스템콜, 인터럽트, 스케줄링, 시스템 자원관리 등의 이유로

- 수시로 사용자 모드에서 커널 모드로 변경된다. 

- 그렇다면 언제 PCB에 존재하는 시스템 콜을 확인하는 걸까? 

- 운영체제가 커널모드에서 사용자모드로 바뀌는 그 시점에, 사용자 모드로 바뀌기 전 마지막 작업으로 PCB의 시그널을 확인한다. 

- 기본 동작을 실행하는 시그널인 경우, 운영체제의 커널 내부에 이미 정의가 되어 있기에 바로 실행이 가능하다.

- 재정의된 동작을 실행하는 시그널의 경우, 프로세스 내부적으로 PC(Program Counter)가 재정의된 동작을 다음 동작으로 가리키도록 바꿔놓는다. 

댓글