비교적 정확한 주기로 특정 액션을 수행할 필요가 있어 SIGALRM을 주기적으로 발생시키는 setitimer() 를 사용해 보았습니다. 그런데 이해 안가는 부분이 있어 기록 차원에 간단한 예제를 만들어 설명해 봅니다.
아래 예제는 100ms 주기로 시간을 찍어서 이전의 시간과의 차이를 출력하는 간단한 예제입니다.
그런데 요부분...
signal(SIGALRM, SIG_IGN); /* note : why??? */
SIGALRM이 발생하면 무시하라는 코드인데, 이 코드가 없으면 SIGALRM이 발생하는 시점에서 프로세스는 종료합니다. 시그널 핸들러를 등록하지 않을 때의 기본 동작입니다.
그런데 setitimer()를 호출하면 sigset 파라메터로 등록된 시그널을 사용하도록 해야 할 것 같고 thread내의 sigwait() 걸리지 않습니다. 실제 구글링을 해봐도 쓰레드와 시그널링 예제들에 이 부분에 대한 언급은 없습니다. 뭔가 간과하고 있는 게 있을 것 같은데....
why??
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | #include <stdio.h> #include <string.h> #include <errno.h> #include <time.h> #include <sys/time.h> #include <pthread.h> #include <signal.h> /* * itimer event thread */ void itimer_event_thread( void *parms) { struct itimerval itimer; sigset_t sigset; int sig_no = 0; struct timeval now; unsigned int time_gap_sec = 0; unsigned int time_gap_usec = 0; printf ( "%s() start!!\n" , __func__); /* * Block alarm signal, will be waited on explicitly */ sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); sigprocmask(SIG_BLOCK, &sigset, NULL); /* * Unblock */ pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); /* * Set up Periodic Interrupt Timer * Start */ itimer.it_value.tv_sec = 0; itimer.it_value.tv_usec = 100*1000; itimer.it_interval = itimer.it_value; if (setitimer(ITIMER_REAL, &itimer, NULL) != 0) { printf ( "Could not start interval timer : %s" , strerror ( errno )); return ; } /* * wait signal forever... */ while (1) { if (sigwait(&sigset, &sig_no) != 0) { printf ( "Failed to wait for next clock tick\n" ); } switch (sig_no) { case SIGALRM: /* * do something here!!! */ gettimeofday(&now, NULL); printf ( "now = %ld.%06ld, gap=%ld.%06ld\n" , now.tv_sec, now.tv_usec, now.tv_sec-time_gap_sec, now.tv_sec-time_gap_usec); time_gap_sec = now.tv_sec; time_gap_usec = now.tv_usec; break ; default : printf ( "unexpected signal %d\n" , sig_no); } } return ; } /* * main function. */ int main() { pthread_t thread ; struct itimerval itimer; sigset_t sigset; int sig_no=0; int rc; signal (SIGALRM, SIG_IGN); /* note : why??? */ /* * Block alarm signal, will be waited on explicitly */ sigemptyset(&sigset); sigaddset(&sigset, SIGALRM ); sigprocmask(SIG_BLOCK, &sigset, NULL); /* * note : block sigset main thread */ pthread_sigmask(SIG_BLOCK, &sigset, NULL); /* * create itimer_event_thread */ rc = pthread_create(& thread , NULL, ( void *)itimer_event_thread, NULL); if (rc) printf ( "itimer_event_thread : %s\n" , strerror ( errno )); else ( void ) pthread_detach( thread ); while (1) usleep(1000); return 0; } |
# signal(SIGALRM, SIG_IGN); 가 빠진 경우
[RXCU][ ~/test ]
(16:39:51 AM) $ !gcc
gcc -lpthread -o tick tick.c
[RXCU][ ~/test ]
(16:39:52 AM) $ ./tick
itimer_event_thread() start!!
Alarm clock
# signal(SIGALRM, SIG_IGN); 가 들어간 경우
[RXCU][ ~/test ]
(16:41:14 AM) $ !gcc
gcc -lpthread -o tick tick.c
[RXCU][ ~/test ]
(16:41:17 AM) $ ./tick
itimer_event_thread() start!!
now = 1382600480.191890, gap=1382600480.1382600480
now = 1382600480.291857, gap=0.1382408590
now = 1382600480.391890, gap=0.1382308623
now = 1382600480.491883, gap=0.1382208590
now = 1382600480.591886, gap=0.1382108597
now = 1382600480.691883, gap=0.1382008594
now = 1382600480.791883, gap=0.1381908597
now = 1382600480.891891, gap=0.1381808597
now = 1382600480.991861, gap=0.1381708589
now = 1382600481.091891, gap=1.1381608620
now = 1382600481.191895, gap=0.1382508590
now = 1382600481.291892, gap=0.1382408586
now = 1382600481.391892, gap=0.1382308589
now = 1382600481.491885, gap=0.1382208589
^C
[RXCU][ ~/test ]
(16:48:33 AM) $ uname -a
Linux ce-devel 2.6.37.1-1.2-desktop #1 SMP PREEMPT 2011-02-21 10:34:10 +0100 i686 i686 i386 GNU/Linux
'IT Tech > Programming' 카테고리의 다른 글
블로그 카테고리 썸네일 이미지로 보기(masonry?) 적용과 문제점 (0) | 2019.01.26 |
---|---|
[C언어] simple hash table - test code (0) | 2012.11.13 |
[SVN] ## 유용한 SVN 부가 명령어들 ## (0) | 2012.09.05 |
[C언어] c/c++ gcc 디버깅을 위한 gdb 초간단 사용팁 (0) | 2012.03.10 |
[C언어] Fast Integer ID Pool 관리 - 할당/반환 함수 (0) | 2011.12.19 |
[C언어] uint2bin (0) | 2011.09.07 |
[Lex&Yacc] Yacc 명령 그리고 Debugging!! (0) | 2011.04.19 |
[C언어] IP 관련 매크로(Macro) (0) | 2011.04.14 |
[regex] 정규표현식 테스트 프로그램 - The Regex Coach (0) | 2011.04.13 |
[C언어] parse Mac Address (0) | 2011.04.08 |