리눅스 타이머 프로그래밍
- 프로그래밍/리눅스 프로그래밍
- 2023. 1. 15.
반응형
리눅스 프로그램에서 시그널(인터럽트) 처리 방식이 아닌 쓰레드 방식의 타이머를 사용할 수 있다.
쓰레드 방식의 타이머를 사용할 경우,
타이머 만기 시에 해당 이벤트를 처리할 수 있는 쓰레드가 생성되므로,
해당 쓰레드(=타이머 만기 처리루틴) 내에서 뮤텍스 등 프로세스 컨텍스트에서만 허용되는 지연 발생 동작을 수행할 수 있다는 장점이 있다.
타이머를 생성하기 위해 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
'프로그래밍 > 리눅스 프로그래밍' 카테고리의 다른 글
리눅스 타이머 프로그래밍 (0) | 2023.01.15 |
---|---|
리눅스 어플리케이션 반복 실행 테스트 방법 (1) | 2022.09.25 |
nanosleep() - 프로세스/쓰레드의 실행을 멈추는(재우는) 함수 (0) | 2022.04.20 |
Kernel PPS 신호 사용하기 (C source code) (0) | 2022.03.26 |
CURL 라이브러리 사용법 - 임베디드 플랫폼용으로 빌드하기(arm-cross-sysroot 활용) (0) | 2021.03.09 |
리눅스 TUN/TAP 디바이스 프로그래밍 (1) | 2021.01.28 |
프로세스 간 통신(IPC) 프로그래밍 - 메시지큐 (0) | 2021.01.19 |
GPSd를 이용한 GNSS 프로그래밍 (0) | 2020.12.24 |