무한 루프 프로그램에게 시그널 보내기
- 무한루프 프로그램 작성 - 무한루프 안에서 자신의 프로세스 아이디(pid) 출력
1
2
3
4
5
6
7
8
9
10 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
while(1){
printf("my pid is %ld \n",(long)getpid());
sleep(1);
}
return 0;
} |
cs |
- kill()을 이용하여 정지시키기 : kill -9 : SIGKILL -> 즉각적으로 죽음
- 무한 루프중 Ctrl+C -> 프로세스를 아예 종료
- 무한 루프중 Ctrl+Z -> stop
- fg -> stop된 프로세스를 다시 재실행
- kill -SIGSTOP
- kill -SIGINT
- sleep(seconds) -> 몇초 기다리다가 다시 실행
- SIGQUIT = Ctrl+\ : 죽기전에 자신의 상태를 파일에 저장 후 죽음 -> 어떤 상황에서 죽었는지 확인 할 수 있음
- 자체적으로 core저장을 막아놓기 때문에 명령어로 저장이 가능하게 해야 함
- ulimit -c unlimited : core를 저장하지 못하도록 막은 것을 풀어줌 -> 너무 큰 파일이 저장 되지 않게 하기 위해서 default로 저장을 막아놓음
- -g : debug정보를 추가한다는 의미
-
debug정보를 추가하여 용량이 늘어남
- gdb ./debug : 디버그 실행
- l : 소스코드 출력
-
enter를 누를때마다 이후의 line이 출력
- b main : break point를 main문에 지정
- r : 실행시작 -> break point에서 걸림
- s : 한줄씩 실행 main에서 fun1으로 들어감 -> fun2 -> fun3
- main -> fun1 -> fun2 -> fun3인 함수를 제작
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
void fun3(){
int i = 0;
while(1){
printf("my pid is %ld \n",(long)getpid());
i++;
sleep(1);
}
}
void fun2(){
fun3();
}
void fun1(){
fun2();
}
int main(){
fun1();
return 0;
} |
cs |
- main문에서 fun1을 부르고 fun1에서 fun2를 .... fun3에서 끝나는 프로그램
- b main으로 break point를 정하고 s를 입력한 후 반복해보면
- bt : 함수가 실행된 순서대로 출력
- q : 나감
GDB를 이용하여 core 파일 분석
- core파일을 통해 어디서 kill되었는지,끝난 이유 등 확인 가능
- gcc -g whiledebug.c
- gdb ./a.out core -> core 확인
- bt : 어디서 중단되었는지 확인
sigaction(2)
- 무한루프 프로그램 수정
- sigaction(2)함수를 써서 SIGINT를 받으면 ouch!를 출력하도록 시그널 핸들러를 작성하여 등록
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 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void ouch(int sig){
printf("OUCH: I got a signal %d\n",sig);
}
int main(){
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
sa.sa_handler = ouch;
if(sigaction(SIGINT,&sa,NULL)==-1){
perror("sigaction");
exit(0);
}
while(1){
printf("my pid is %ld \n",(long)getpid());
sleep(1);
}
return 0;
} |
cs |
- sigaction을 사용하기 위한 struct선언
- sigemptyset으로 mask를 비워줌
- flag를 0으로 선언
- handler에 ouch라는 함수 지정
- sigaction사용 -> SIGINT에 ouch함수 지정 -> -1이면 에러
- 결과
- 원래 while문이 진행되다가 Ctrl+C를 입력하면 ouch실행
추가로 SIGQUIT을 받으면 good bye를 출력하고 종료
- 위의 파일에서 함수 하나만 더 추가하면 됨
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
31
32
33
34
35
36
37
38
39
40
41
42
43 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void ouch(int sig1){
printf("OUCH: I got a signal %d\n",sig1);
}
void bye(int sig2){
printf("Good bye %d\n",sig2);
exit(0);
}
int main(){
struct sigaction sa;
struct sigaction sa_quit;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
sa.sa_handler = ouch;
sigemptyset(&sa_quit.sa_mask);
sa_quit.sa_flags=0;
sa_quit.sa_handler = bye;
if(sigaction(SIGINT,&sa,NULL)==-1){
perror("sigaction");
exit(0);
}
if(sigaction(SIGQUIT,&sa_quit,NULL)==-1){
perror("sigaction");
exit(0);
}
while(1){
printf("my pid is %ld \n",(long)getpid());
sleep(1);
}
return 0;
} |
cs |
- 결과
alarm(2)
- 무한루프 프로그램 수정
- alarm(2) 함수를 통해 매 1초마다 SIGALRM을 발생
- sigaction(2) 함수를 써서 SIGALRM를 받으면 Alarm arrived!를 출력하도록 시그널 핸들러를 작성하여 등록
- alarm은 한번만 SIGALRM을 발생시킨다 주기적으로 SIGALRM을 발생시키기 위해서는 SIGALRM시그널 핸들러에서도 alarm(2)을 설정해 주어야 한다 -> 완전히 끝내 줘야 다시 호출할 수 있음
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 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void al(int sig){
printf("Alarm arrived!\n");
alarm(2);
}
int main(){
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
sa.sa_handler = al;
if(sigaction(SIGALRM,&sa,NULL)==-1){
perror("sigaction");
exit(0);
}
alarm(2);
while(1){
printf("my pid is %ld \n",(long)getpid());
sleep(1);
}
return 0;
} |
cs |
- 위와 마찬가지로 struct sigaction을 정의 sa
- flag = 0
- handler = al함수로 지정
- SIGALRM에 sa를 지정하면 알람이 올때마다 handler로 지정된 al함수 실행
- alarm(2)를 al함수에 넣어주는 이유는 한번 실행하고 while문이 반복되기 때문에 다시 alarm을 실행하지 못하기때문
- 결과
- sleep(1)이므로 1초마다 while문이 실행
- 2번의 실행 후 alarm이 실행됨
sigprocmask(2)
- 주어진 코드
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
31
32
33
34
35
36
37
38 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
struct two_double{
double a;
double b;
}data;
void signal_handler(int sig){
printf("%f, %f\n",data.a,data.b);
alarm(1);
}
int main(void){
struct sigaction sa;
static struct two_double zeros={0.0,0.0}, ones={1.0,1.0};
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
sa.sa_handler = signal_handler;
if(sigaction(SIGALRM,&sa,NULL)==-1){
perror("sigaction");
exit(0);
}
data = zeros;
alarm(1);
while(1){
data = zeros;
data = ones;
}
return 0;
} |
cs |
- 의도한 결과 : 0.0 0.0 혹은 1.0 1.0이 번갈아가면서 출력되는 함수
- 결과
- 0 0/ 1 1 뿐만 아니라 0 1/ 1 0도 함께 출력되는 것을 볼 수 있음
- 원인? : alarm(1)에 의하여 handler는 1초에 한 번씩 출력을 하는데 while문이 빠르게 동작하면서 값이 바뀌는 중간에 swiching 되기 때문
- sigprocmask(2)를 이용하여 의도한 코드를 완성시켜 보자
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 |
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
struct two_double{
double a;
double b;
}data;
void signal_handler(int sig){
printf("%f, %f\n",data.a,data.b);
alarm(1);
}
int main(void){
struct sigaction sa;
static struct two_double zeros={0.0,0.0}, ones={1.0,1.0};
sigset_t block_set, prev_set;
sigemptyset(&block_set);
sigaddset(&block_set,SIGALRM);
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
sa.sa_handler = signal_handler;
if(sigaction(SIGALRM,&sa,NULL)==-1){
perror("sigaction");
exit(0);
}
sigprocmask(SIG_BLOCK,&block_set,&prev_set);
data = zeros;
alarm(1);
while(1){
sigprocmask(SIG_SETMASK,&prev_set,NULL);
sigprocmask(SIG_BLOCK,&block_set,&prev_set);
data = ones;
sigprocmask(SIG_SETMASK,&prev_set,NULL);
sigprocmask(SIG_BLOCK,&block_set,&prev_set);
data = zeros;
}
return 0;
} |
cs |
- procmask에 SIGALRM을 추가하여 alarm의 signal을 막아줌
- data를 바꾸기전에 alarm을 block해준 후 모두 바뀌고 이전 값을 set해줌
- 이렇게 하면 데이터가 바뀌는 중간에 alarm이 걸리지 않아서 결과가 0 0혹은 1 1이 나오게 됨
- 결과
'LINUX 실습' 카테고리의 다른 글
POSIX Threads - create 부터 Mutex까지 (0) | 2018.12.04 |
---|---|
[함수 만들기]프로세스 시스템 콜 (0) | 2018.11.26 |
[시스템 콜 파일(2)]myls, mycp2 함수 만들기 (0) | 2018.11.18 |
[File I/O]시스템 콜을 이용하여 함수 만들기 (0) | 2018.11.12 |
[System call 실습]System call의 기본 개념 (0) | 2018.11.02 |