리눅스 타이머 프로그래밍

반응형

리눅스 프로그램에서 시그널(인터럽트) 처리 방식이 아닌 쓰레드 방식의 타이머를 사용할 수 있다.

 

쓰레드 방식의 타이머를 사용할 경우,

타이머 만기 시에 해당 이벤트를 처리할 수 있는 쓰레드가 생성되므로,

해당 쓰레드(=타이머 만기 처리루틴) 내에서 뮤텍스 등 프로세스 컨텍스트에서만 허용되는 지연 발생 동작을 수행할 수 있다는 장점이 있다.

 

타이머를 생성하기 위해 timer_create() 호출 시, 인자로 전달하는 sigevent 구조체의 sigeve_notify 변수의 값을 SIGEV_THREAD로 설정함으로써 쓰레드 기반의 타이머를 사용할 수 있다.

 

이 경우 타이머 만기 시마다,

sigevent 구조체의 sigeve_notify_function 변수에 연결된 쓰레드 함수를 수행하는 쓰레드가 생성되며, 해당 쓰레드 함수 내에서 타이머 만기 시에 수행할 동작을 구현할 수 있다.

 

사용되는 함수는 timer_create(), timer_settime() 이다.

 

타이머 구현의 예제는 다음과 같다.

// timer2.c

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

#define INITIAL_DELAY (1000) ///< 최초 타이머 만기 지연 (밀리초 단위)
#define INTERVAL (100) ///< 타이머 만기 주기 (밀리초 단위)


/**
 * @brief 타이머 만기 시 실행되는 쓰레드  
 * @param arg 사용되지 않음 
 */
static void timer_expired_thread(union sigval arg)
{
  (void)arg;

  /* 
   * TODO 
   * 시그널(인터럽트) 처리 함수가 아닌 쓰레드 함수이므로 뮤텍스 등 프로세스 컨텍스트에서 사용할 수 있는 지연 동작을 사용할 수 있다. 
   */

  printf("Timer expired\n");
}


/**
 * @brief 메인 함수 
 * @return int 
 */
int main(void) 
{
  struct itimerspec ts;

  /*
   * 최초 타이머 만기 주기를 설정한다.
   */
  ts.it_value.tv_sec = INITIAL_DELAY / 1000;
  ts.it_value.tv_nsec = (INITIAL_DELAY % 1000) * 1000000;

  /*
   * 두번째부터의 타이머 주기를 설정한다.
   */
  ts.it_interval.tv_sec = INTERVAL / 1000;
  ts.it_interval.tv_nsec = (INTERVAL % 1000) * 1000000;

  /*
   * 타이머를 생성한다 - 타이머 만기 시 쓰레드가 생성되도록 설정한다 (SIGEV_THREAD).
   */
  timer_t timer;
  struct sigevent se;
  se.sigev_notify = SIGEV_THREAD;
  se.sigev_value.sival_ptr = &timer;
  se.sigev_notify_function = timer_expired_thread;
  se.sigev_notify_attributes = NULL;
  int ret = timer_create(CLOCK_MONOTONIC, &se, &timer);
  if (ret < 0) {
    perror("timer_create() ");
    return -1;
  }

  /*
   * 타이머에 주기를 설정한다.
   */
  ret = timer_settime(timer, 0, &ts, NULL);
  if (ret < 0) {
    perror("timer_settime() ");
    return -1;
  }

  /*
   * 프로세스 실행 유지
   */
  while (1) {
    sleep(1);
  }

  return 0;
}

 

다음과 같이 빌드한다.

gcc -o timer2 timer2.c -lrt

 

빌드된 파일을 실행하면 다음과 같이 주기적으로 출력되는 것을 확인할 수 있다.

root# ./timer2
Timer expired
Timer expired
Timer expired
Timer expired
Timer expired
Timer expired

댓글

Designed by JB FACTORY