달력

52024  이전 다음

  • 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

'timeval'에 해당되는 글 1건

  1. 2010.03.31 struct timeval & long long
현재 시각을 측정하는 손쉬운 방법은 gettimeofday()를 이용하는 것으로,
이때 struct timeval 구조체를 이용하게 된다.

<API>
int gettimeofday(struct timeval *tv, struct timezone *tz);

<example>
struct timeval tv;
if (!gettimeofday(&tv, NULL)) fprintf(stderr, "%s error at %d\n", __FUNCTION__, __LINE__);


그리고 /usr/include/sys/time.h 파일을 보면 다음과 같은 편리한 macro를 제공함을 알 수 있다.
__USE_BSD 가 언제 #define 되는지 모르겟지만 이용 할 수 있었다.
stuct timeval 에 sec 부분과 usec 부분으로 분리되어 있는데 아래 3개 macro는 유용할 것이다.
timercmp(a, b, CMP)
timeradd(a, b, result)
timersub(a, b, result)
예를 들어 현재 시각을 매번 측정하여 그 차이를 위의 timersub를 통해 손쉽게 계산할 수 있고,
그 차이를 timeradd를 통해 손쉽게 계속 더해갈 수 있다.

#ifdef __USE_BSD
/* Convenience macros for operations on timevals.
   NOTE: `timercmp' does not work for >= or <=.  */
# define timerisset(tvp)        ((tvp)->tv_sec || (tvp)->tv_usec)
# define timerclear(tvp)        ((tvp)->tv_sec = (tvp)->tv_usec = 0)
# define timercmp(a, b, CMP)                                                  \
  (((a)->tv_sec == (b)->tv_sec) ?                                             \
   ((a)->tv_usec CMP (b)->tv_usec) :                                          \
   ((a)->tv_sec CMP (b)->tv_sec))
# define timeradd(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec;                          \
    if ((result)->tv_usec >= 1000000)                                         \
      {                                                                       \
        ++(result)->tv_sec;                                                   \
        (result)->tv_usec -= 1000000;                                         \
      }                                                                       \
  } while (0)
# define timersub(a, b, result)                                               \
  do {                                                                        \
    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                             \
    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                          \
    if ((result)->tv_usec < 0) {                                              \
      --(result)->tv_sec;                                                     \
      (result)->tv_usec += 1000000;                                           \
    }                                                                         \
  } while (0)
#endif  /* BSD */

그런데 struct timeval 을 그대로 이용할 때는 불편할 때가 있다.
예를 들어 sec을 일부와 usec의 일부만을 출력하거나
다른 일반 int type으로 저장한 시간과 비교할 때가 그럴 수 있을 것이다.

(어디까지나 선택사항이지만) 이때는 struct timeval 을 long long 으로 변환해서 저장하는 것이 편하다.
아래와 같이 long long time 에 저장하는 것이다.
time = tv.tv_sec * 1000000LL + tv.tv_usec;

참고적으로 혹시 전환 과정에서 data 손실을 우려할 수 있으나 그렇지 않다.
long long type이 보통 8byte 이고, struct timeval의 tv_sec 과 tv_usec 이 각각 4byte 인데,
실제로는 tv_usec의 값은 최대 10^6 - 1 로서, 이는 2진수 값으로 20bit 이하이다.
따라서 20bit 인 2.5byte를 shift 하더라도 데이터 손실이 없는 것이다.

아래는 관련해서 테스트한 소스 코드이며,
struct timeval : 1270047284.534099
long long      : 1270047284534099
실행결과 바로 위와 같이 두 값이 같음을 알 수 있다.

#include <stdio.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
        struct timeval tv;
        long long time;

        if (gettimeofday(&tv, NULL)) fprintf(stderr, "%s error at %d\n", __FUNCTION__, __LINE__);
        time = tv.tv_sec * 1000000LL + tv.tv_usec;

        printf("struct timeval : %d.%-6d\n", (int)tv.tv_sec, (int)tv.tv_usec);
        printf("long long      : %lld\n", time);

        return 0;
}

'Lang, Tool, Env' 카테고리의 다른 글

Ubuntu /home 옮기기  (0) 2012.08.04
struct 내 flag용으로 쓸 1bit 크기 변수 사용하기  (0) 2010.05.09
IEEE Floating-Point Format  (1) 2009.09.13
chroot  (0) 2008.04.06
임베디드 기초 교육 정리  (0) 2007.08.26
Posted by neodelicious
|