본문 바로가기

IT Tech/Programming

[C언어] Linux Pthread & Signal, Itimer 간단 예제와 의문!!

반응형




비교적 정확한 주기로 특정 액션을 수행할 필요가 있어 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










반응형