gettimeofday를 대체하는 clock_gettime 함수
http://sunyzero.tistory.com/161
gettimeofday는 유닉스, 리눅스 시스템 프로그래밍에서 시간을 구할 때 쓰던 함수이다. 마이크로초(백만분의 1초)단위로 구할 수 있는 기능을 가지고 있어서 많이 사용되는 함수이다.
그러나 앞으로는 gettimeofday는 사용하지 말아야할 함수가 되었다. 왜냐하면 gettimeofday는 2008년도 유닉스 표준인 SUSv4-2008에서 앞으로 제거될 구식(obsolescent) 함수로 지정했기 때문이다.
물론 하위 호환성을 위해서 gettimeofday 함수는 계속 제공될 것이다. 하지만 기본 시스템 라이브러리에서는 제거되고, 구식 라이브러리를 따로 포함해야 사용할 수 있게 될지도 모르기 때문에 차후에는 gettimeofday는 쓰지 않는 편이 좋다. 참고로 지금까지의 표준안의 행보로 봤을 때 obsolescent 함수로 지정되면 약 10여년의 유예를 거치는 것 같다. 따라서 지금 당장부터 쓰지 말아야 하는 것은 아니다.
대신에 새로운 함수인 clock_gettime을 사용하면 된다.
gettimeofday는 1988년도에 SVR4에서 표준에 지정되어 20여년을 넘게 사용되던 함수이다. 아직도 수많은 프로그래밍 서적이나 소스 코드의 예제에서 사용되고 있다. 실제로 최근에 개발되던 몇몇 실무 코드 조차 gettimeofday를 사용하고 있는 실정이다.
하지만 가까운 장래에는 퇴출될 함수이므로 지양하는 편이 좋다. 본인도 가끔 졸린 상태에서 기계적으로 코딩하다보면 gettimeofday를 쓰곤 하는데 지양하도록 주의하는 중이다.
그러면 새로운 함수인 clock_gettime의 프로토 타입부터 살펴보자. 비교를 위해 과거 gettimeofday 도 같이 적어두었다.
02 |
int clock_gettime(clockid_t clock_id, struct timespec *tp); |
07 |
-------------------------------------------------------------- |
09 |
int gettimeofday( struct timeval *restrict tp, void *restrict tzp); |
먼저 clock_gettime은 시간 관련 구조체가 struct timespec으로 바뀌었는데 나노초까지 지정할 수 있다. 물론 모든 시스템이 나노초까지 정밀한 시계를 제공하는 것은 아니다. 각 시스템 시계의 정밀도는 clock_getres로 확인할 수 있다.
또한 clock_gettime은 멀티코어 CPU 시대에 걸맞게 쓰레드 안전(thread safety)을 만족하고 있다.
인수로 쓰이는 clockid_t 타입은 시계의 종류를 나타내는 ID로서 POSIX 시스템은 기본적으로 2가지 타입(CLOCK_REALTIME, CLOCK_MONOTONIC)의 시계를 제공한다. 그리고 추가적으로 몇 개의 시계를 더 제공할 수 있다. 아래 표를 보면 몇몇 시계 ID를 정리해두었다. 그러나 실제 시스템에서는 이보다 더 많은 비표준 시계 ID를 제공하기도 한다.
CLOCK_REALTIME |
시스템 전역의 실제 시계(The UNIX Epoch 시간) |
CLOCK_MONOTONIC |
단조 시계 (특정 시점에서 흐른 시간, 대체적으로 부팅후 시간) |
CLOCK_PROCESS_CPUTIME_ID |
프로세스 단위 CPU 사용 시간 |
CLOCK_THREAD_CPUTIME_ID |
쓰레드 단위 CPU 사용 시간 |
여기서 CLOCK_REALTIME을 사용하면 실제 시간을 구하므로 gettimeofday의 기능과 같은 기능을 제공한다. 이제 현재 시각을 버퍼에 저장하는 간단한 예제 코드를 살펴보자.
main 함수는 생략했으니 적당히 붙여서 코딩하면 될 것이다. 화면에 출력되는 것을 보고 싶다면 printf로 buf 문자열을 출력하면 된다.
01 |
#define STR_TIME_FORMAT "%y-%m-%d/%H:%M:%S" |
03 |
size_t sz_buf = sizeof (buf); |
04 |
struct timespec tspec; |
08 |
if (clock_gettime(CLOCK_REALTIME, &tspec) == -1) { |
13 |
localtime_r(( time_t *)&tspec.tv_sec, &tm_now); |
16 |
if ( strftime (buf, sz_buf, STR_TIME_FORMAT, &tm_now) == 0) { |
참고로 gettimeofday 외에 usleep, getitimer, setitimer도 구식(obsolescent) 함수로 지정되어 나중에는 사라질 함수이므로 되도록이면 쓰지 않는 편이 좋다.