double인 이유는 시스템에 따라 시간 값이 long / int / 실수 형으로 반환하는 경우도 있기 때문에 double로 잡혀있다.
Displaying date and time
#include<time.h>// parameter가 tm 구조체. 기능은 ctime과 같음char*asctime(conststructtm*timeptr);// string으로 반환해 줌. 사람이 보기 편한 형태 ( 26개의 영어 string + \n )char*ctime(consttime_t*clock);// localtime이 아니라, utc 기준으로 tm 구조체를 반환structtm*gmtime(consttime_t*timer);// timer의 정보를 받아서 parsing => struct tm 으로 반환structtm*localtime(consttime_t*timer);
asctime, ctime, localtime은 thread-safe하지 않다. 충돌이 일어날 수 있다.
내부적으로 static 변수를 사용하기 때문
struct tm structure
Members
int tm_sec; /* seconds [0,59] */
int tm_min; /* minutes [0,59] */
int tm_hour; /* hours [0,23] */
int tm_mday; /* day of the months [1,31] */
int tm_mon; /* months [0, 11] */ ⇒ 실제 월은 + 1
int tm_year; /* years since 1900 */ ⇒ 1900년 부터 몇년이 흘렀냐
int tm_wday; /* days since Sunday [0,6] */
int tm_yday; /* days since January 1 [0, 365] */
int tm_isdst; /* flag for daylight-saving time */ ⇒ summer time 제를 시행하는지 아닌지 ( 필요 없음 )
고정된 interval로 값을 계속 증가시키는 counter이다. ( clock resolution ⇒ tick이 발생하는 interval )
clock resolution이 1s 이라면, 나노세컨 단위를 알 수가 없다.
clock_id ⇒ 어떠한 clock을 사용할 것인지 알려준다.
현재 시간을 알려주는 CLOCK_REALTIME을 사용해도 된다.
clock 종류를 더 알고 싶다면 man clock_getres.. ( CLOCK_REALTIME_COARSE, CLOCK_MONOTONIC… )
struct timespec structure
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
retrun values
성공했을 시 0
실패했을 시 -1
Example using real-time clocks
#include<stdio.h>#include<time.h>#defineMILLION1000000Lvoidfunction_to_time(void);intmain(void){long timedif;structtimespec tpend, tpstart;if(clock_gettime(CLOCK_REALTIME,&tpstart)==-1){perror("Failed to get starting time");return1;}function_to_time();/* timed code goes here */if(clock_gettime(CLOCK_REALTIME,&tpend)==-1){perror("Failed to get ending time");return1;}
timedif = MILLION*(tpend.tv_sec - tpstart.tv_sec)+(tpend.tv_nsec - tpstart.tv_nsec)/1000;printf("The function_to_time took %ld microseconds\n", timedif);return0;}
value: itimespec 구조체인 value / interval 객체를 줄 수 있다.
ovalue: 이전의 타이머 값을 저장하기 위한 output 파라미터
timer_gettime
value: output 파라미터 / 현재 남아있는 타이머 정보 값을 반환한다.
time_getoverrun
overrun 횟수를 반환받기 위함
타이머가 한번만 실행되고 말 경우에는 아니지만, 반복되는 타이머의 경우에 발생할 수 있음
만료되고 나서 시그널이 발생되는데, 프로세스가 그 시그널을 받아서 처리를 하고, 다시 타이머가 작동하고 …의 반복
타이머가 만료가 되고 나서 시그널을 발생시켜 프로세스에게 전달이 되었는데, 시그널이 프로세스에게 전달되지 못하고 pending된 경우 pending list에 들어가있고, 다시 타이머가 진행되는 경우 다시 또 시그널이 발생될 것이다. 다음 시그널이 발생되어 프로세스에게 전달이 될 것인데 또 pending이 된다면? pending list에는 같은 타입의 시그널이 들어있을 수 없기 때문에 기존 시그널이 덮여쓰여진다.
즉, pending이 되면서 덮여 쓰여진 ( 없어진 ) 시그널의 개수를 overrun 이라고 한다.
Example
#include<stdio.h>#include<time.h>#defineMILLION1000000L#defineTHOUSAND1000void function_to-time(void);intmain(void){long diftime;structitimerspec nvalue, ovalue;
timer _t timeid;// tmr timer를 사용하기 위해 timer를 만든다.if(timer_create(CLOCK_REALTIME,NULL,&timeid)==-1){perror("Failed to create a timer based on CLOCK_REALTIME");return1;}
ovalue.it_interval.tv_sec =0;
ovalue.it_interval.tv_nsec =0;
ovalue.it_value.tv_sec = MILLION;
ovalue.it_value.tv_nsec =0;if(timer_settime(timeid, O,&ovalue,NULL)==-1){
perror"Failed to set interval timer"i;return1;}function_to_time();if(timer_gettime(timeid,&nvalue,==-1){perror("Failed to get interval timer value");return1;}
diftime = MILLION*(ovalue.it_value.tv_sec - nvalue.it_value.tv_sec)+(ovalue.it_value.tv._nsec - nvalue.it_value.tv_nsec)/THOUSAND;printf("The function_to_time took %ld microseconds or %f seconds.\n",
diftime, diftime/(double}MILLION);return0;}
Timer drift
계속 반복해서 타이머를 사용하는 경우에는 timer drift를 고려해야한다.
만료 시점이 delay가 생겨, 생각보다 나중에 타이머가 만료되는 경우
이유
타이머의 태생적인 이유 ⇒ 완전히 0으로 만들 수는 없다
타이머가 반복해서 실행이 되면, 만료된 이후 다시 시작하는 시점까지의 delay가 미세하게 존재한다.
Example
22ms의 interval을 가진 timer의 resolution이 10ms 라고 하자.
22가 표현이 되지 않기 때문에 8ms의 delay가 각각의 만료 시점마다 생기게 된다.
+ 다음 시점은 44를 원하지만, 30인 시점에 시작을 하면 60인 시점에 만료가 된다.
Solution
interval을 계속 22로 하는 것이 아니라, 다음 시점은 원래의 기대값으로 갈 수 있을 만큼만 ( 14 )
계속 timer drift가 증가되는 문제를 해결할 수는 있다.
Save T = current time + 22 ms
Set the timer to expire in 22 ms
In the signal handler, set the timer to expire in (T – current time + 22ms), and T = T + 22 ms
Solution
POSIX:TMR timer absolute time를 사용해라
timer_settime의 flags에 TIMER_ABSOLUTE를 세팅하면 된다.
*value field의 it_value에 absolute time으로 설정할 수 있다.
현재 시간을 clock_gettime으로 가져온 뒤 22ms를 더하고 이것을 T로 저장한다.
T값을 timer의 만료 시점으로 정하면 된다. ( TIMER_ABSOLUTE 태그를 사용하여 )