Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

81235
1036
103651


[리눅스커널][시그널] 시그널 설정은 어떻게 할까? 12장. 시그널


이번 절에서는 시그널을 설정하면 유저 공간에서 커널 공간까지 어떤 흐름으로 처리하는지 소스 코드를 보면서 살펴 보겠습니다.

유저 공간 시그널 설정 

유저 레벨 프로세스에서 시그널 설정을 어떻게 하는지 소스 코드와 함께 살펴봅시다. 유저 공간에서 시그널을 설정하는 간단한 코드입니다.
1 #include <unistd.h>
2 #include <signal.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 void sig_handler(int signum) {
7 switch(signum) {
8    case SIGINT:
9       printf("sig num [%d] \n", signum);
10 break;
11
12    case SIGALRM:
13 printf("sig num [%d] \n", signum);
14 break;
15
16    case SIGUSR1:
17 printf("sig num [%d] \n", signum);
18 break;
19
20   default:
21 printf(" default sig num [%d] \n", signum);
22 }
23 }
24 
25 int main() 
26 {
27 struct sigaction act;
28 sigset_t set;
29
30 sigemptyset(&(act.sa_mask));
31
32 sigaddset(&(act.sa_mask), SIGALRM);
33 sigaddset(&(act.sa_mask), SIGINT);
34 sigaddset(&(act.sa_mask), SIGUSR1);
35
36 act.sa_handler = sig_handler;
37
38 sigaction(SIGALRM, &act, NULL);
39 sigaction(SIGINT, &act, NULL);
40 sigaction(SIGUSR1, &act, NULL);
41
42    for (;;)
43 pause();
44 }


이번 장은 시그널을 리눅스 커널에서 어떻게 처리하는지 초점을 맞춥니다. 따라서 유저 어플리케이션에서 시그널을 설정하는 코드는 최대한 간단히 소개합니다.

위 코드는 SIGALRM, SIGINT, SIGUSR1 시그널을 sig_handler() 함수를 시그널 핸들러로 등록합니다. 3가지 시그널이 전달되면 sig_handler() 함수를 호출하는 동작입니다. 

30번째 줄 코드부터 봅시다.
30 sigemptyset(&(act.sa_mask));
31
32 sigaddset(&(act.sa_mask), SIGALRM);
33 sigaddset(&(act.sa_mask), SIGINT);
34 sigaddset(&(act.sa_mask), SIGUSR1);

30~34번째 줄 코드는 sigemptyset() 함수를 써서 시그널 집합을 초기화한 후 sigaddset() 함수로 SIGALRM, SIGINT, SIGUSR1 시그널을 추가합니다.

다음 36~40번째 줄 코드를 분석하겠습니다.
36 act.sa_handler = sig_handler;
37
38 sigaction(SIGALRM, &act, NULL);
39 sigaction(SIGINT, &act, NULL);
40 sigaction(SIGUSR1, &act, NULL);

act.sa_handler에 sig_handler() 이란 시그널 핸들러 함수를 등록합니다. sigaction() 함수를 호출해서 프로세스가 SIGALRM, SIGINT, SIGUSR1 시그널 중 하나를 받으면 시그널 핸들러로 sig_handler() 함수를 실행하도록 지정합니다.

다음 42~43번째 줄 코드를 보겠습니다.
42    for (;;)
43 pause();

pause() 함수는 시그널을 받을 때까지 기다리는 역할을 수행합니다.

다음은 SIGALRM, SIGINT, SIGUSR1 시그널이 발생하면 리눅스 커널에서 호출하는 시그널 핸들러 함수인 sig_handler()를 분석하겠습니다.
6 void sig_handler(int signum) {
7 switch(signum) {
8    case SIGINT:
9       printf("sig num [%d] \n", signum);
10 break;
11
12    case SIGALRM:
13 printf("sig num [%d] \n", signum);
14 break;
15
16    case SIGUSR1:
17 printf("sig num [%d] \n", signum);
18 break;
19
20   default:
21 printf(" default sig num [%d] \n", signum);
22 }
23 }


sig_handler() 함수와 같은 시그널 핸들러는 직접적으로 누가 언제 실행할까요? 주인공은 리눅스 커널입니다. 시그널을 받은 프로세스가 시그널 핸들러를 실행하도록 리눅스 커널은 지원합니다. 

sig_handler() 함수는 SIGINT, SIGALRM, SIGUSR1 시그널이 전달되면 실행하는 시그널 핸들러 함수입니다. 시그널 번호를 signum 인자로 받아서 출력하는 역할을 수행합니다.

시그널은 어떻게 생성할 수 있을까요?
Ctl+C 키를 누르거나 alarm(), kill()과 같은 리눅스 표준 함수를 호출하면 커널은 SIGINT와 SIGALRM 시그널을 생성한 다음 시그널 핸들러로 등록한 sig_handler() 함수를 실행합니다.

커널에서 시그널을 어떻게 처리하는지 살펴보는 것이 이 장의 핵심입니다. 따라서 유저 프로세스 입장에서 시그널을 설정하는 기본 코드를 알아봤습니다.

다음 소절에서는 커널 입장에서 시그널을 설정할 때 어떤 코드 흐름인지 알아보겠습니다.

커널 공간에서 시그널은 어떻게 설정할까? 

이전 절에서는 유저 프로세스에서 시그널을 설정하는 코드를 살펴봤습니다. 이번 소절에서는 커널에서는 시그널을 설정하면 어떤 동작을 하는지 살펴보겠습니다.
 
유저 프로세스가 시그널 설정을 위해 리눅스 표준 함수를 쓰면 시스템 콜을 발생해서 해당 시스템 콜 핸들러를 실행합니다. sigaddset()와 같이 시그널 자료구조만 변경하는 함수는 시스템 콜을 발생하지 않고 커널에 시그널 설정을 요청하는 sigaction() 함수나 시그널을 기다리는 pause() 와 같은 함수를 호출할 때 시스템 콜을 발생합니다.

다음 소절에서는 커널에서 지원하는 시스템 콜 핸들러를 소개합니다.

시그널 관련 시스템 호출 함수는 무엇일까?  

시그널 관련 시스템 호출 함수는 다음과 같습니다.
시스템 콜 시스템 콜 핸들러 동작
kill sys_kill 쓰레드 그룹에 시그널을 보냄
tkill sys_tkill 프로세스에 시그널을 보냄
tgkill sys_tgkill 특정 쓰레드 그룹에 있는 프로세스에게 시그널을 보냄
sigaction sys_rt_sigaction 시그널 속성 설정
sigpending sys_rt_sigpending 펜딩된 시그널이 있는지 점검
sigprocmask sys_rt_sigprocmask 블록되어 있는 시그널 집합을 수정
sigsuspend sys_rt_suspend 시그널을 기다림
pause sys_pause 시그널을 수신할 때 까지 기다림

가장 왼쪽 행에 보이는 kill, tgkill과 같은 함수 이름은 유저 공간에서 호출하는 리눅스 저수준 표준 함수입니다. 이 함수를 호출하면 시스템 콜을 발생시켜 커널 공간에서 sys_kill(), sys_tgkill()과 같은 시스템 콜 핸들러 함수를 실행합니다.

이번 장에서 리눅스 표준 함수를 호출하면 어떤 흐름으로 시스템 콜 핸들러를 실행하는지 살펴봅니다. 또한 시스템 콜 핸들러 후속 함수 처리로 리눅스 커널이 시그널을 어떻게 처리하는지 상세히 분석합니다.


#Referene 시그널

시그널이란
시그널 설정은 어떻게 할까
시그널 생성 과정 함수 분석
프로세스는 언제 시그널을 받을까
시그널 전달과 처리는 어떻게 할까?
시그널 제어 suspend() 함수 분석 
시그널 ftrace 디버깅

"혹시 궁금점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답글 올려드리겠습니다!" 

핑백

덧글

댓글 입력 영역