setitimer , getittimer 값이 이해가 안되네요

shamlock의 이미지

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

#define MILLION 1000000L


int main(void)
{
    int i;
    long diftime;
    struct itimerval a, b;

    a.it_interval.tv_sec = 0;
    a.it_interval.tv_usec = 0;
    a.it_value.tv_sec = MILLION; /* a large number */
    a.it_value.tv_usec = 0;

    if (setitimer(ITIMER_VIRTUAL, &a, NULL) == -1)
    {
       perror("Failed to set virtual timer");
       return 1;
    }

    for(i=0;i<10;i++)
    {
        printf(".");
        fflush(stdout);
        usleep(1000);
    }

    if (getitimer(ITIMER_VIRTUAL, &b) == -1)
    {
       perror("Failed to get virtual timer");
       return 1;
    }

    printf("\n처음 설정 시간: %06ld초.%06ld" , a.it_value.tv_sec, a.it_value.tv_usec);
    printf("\n남은시간      : %06ld초.%06ld" , b.it_value.tv_sec, b.it_value.tv_usec);
    printf("\n");
    diftime = MILLION*(a.it_value.tv_sec - b.it_value.tv_sec) + a.it_value.tv_usec - b.it_value.tv_usec;
    printf("The function_to_time took %ld microseconds or %f seconds.\n",
            diftime, diftime/(double)MILLION);
    return 0;
}

a.out
..........
처음 설정 시간: 1000000초.000000
남은시간      : 1000000초.010000
The function_to_time took -10000 microseconds or -0.010000 seconds.

왜 남은 시간이 더 큰거죠?

shamlock의 이미지

..

@.@

pynoos의 이미지

struct itimerval 의 필드값을 잘 못이해하신것 같습니다.

둘이 합쳐하나의 시간을 말하는 것이 아니라, 하나는 만료시간이고, 하나는 지난시간입니다.

shamlock의 이미지

책에는 이렇게 나오거든요

struct timeval it_value;    /* time until next expiration */
struct timeval it_interval; /* value to reload into the timer */

Here it_value holds the time remaining before the timer expires, and it_interval holds the time interval to be used for resetting the timer after it expires. Recall that a struct timeval structure has fields for seconds and microseconds.

Kay A.Robbins, Steven Robbins 공저

글구 맨페이지를 봐도 비슷한 내용인데..

int getitimer(int which, struct itimerval *value);
  Getitimer(2)    는   ITIMER_REAL,   ITIMER_VIRTUAL,     나
                 ITIMER_PROF  중 하나에 의해 지정된 타이머를 위해 현재 설정
                 한 value 에 의해 지정된 구조로 채워진다.  it_value 는 타이
                 머 에 남겨진 시간의 양으로 설정되거나 타이머가 작동하지 않
                 으면 0이다.  비슷하게, it_interval 는 reset 값으로 설정 된
                 다.   Setitimer(2)  는 value 값으로 지정된 타이머를 설정한
                 다.  ovalue 가 0이 아니면, 타이머의 이전 값은 그곳에 저 장
                 된다.

@.@

shamlock의 이미지

아침부터 ... 이런 저런 테스트하게 되네요
위의 소스코드에서 ITIMER_VIRTUAL을 ITIMER_REAL로 설정하니깐

실행결과가 예상했던대로 남아 있는 시간이 나오네요

ITIMER_VIRTUAL은 프로세스가 실행한 시간(sleep 이나 블럭킹은 빼고)
ITIMER_REAL는 경과한 벽시계 시간
인 것으로 이해하고 있었는데 그렇다면 ITIMER_VIRTUAL을 ITIMER_REAL이 비슷하게 나와야할 것 같은데..이상하네요

#include <stdio.h>
#include <sys/time.h>
#define MILLION 1000000L


int main(void)
{
    int i;
    long diftime;
    struct itimerval a, b;

    a.it_interval.tv_sec = 0;
    a.it_interval.tv_usec = 0;
    a.it_value.tv_sec = MILLION; /* a large number */
    a.it_value.tv_usec = 0;

    //if (setitimer(ITIMER_VIRTUAL, &a, NULL) == -1) 
    if (setitimer(ITIMER_REAL, &a, NULL) == -1)
    {
       perror("Failed to set virtual timer");
       return 1;
    }

    for(i=0;i<10;i++)
    {
        printf("%d\n",i);
        fflush(stdout);
        usleep(1000);
    }

    if (getitimer(ITIMER_REAL, &b) == -1)
    {
       perror("Failed to get virtual timer");
       return 1;
    }

    printf("\n처음 설정 시간: %06ld초.%06ld" , a.it_value.tv_sec, a.it_value.tv_usec);
    printf("\n남은시간      : %06ld초.%06ld" , b.it_value.tv_sec, b.it_value.tv_usec);
    printf("\n");
    diftime = MILLION*(a.it_value.tv_sec - b.it_value.tv_sec) + a.it_value.tv_usec - b.it_value.tv_usec;
    printf("The function_to_time took %ld microseconds or %f seconds.\n",
            diftime, diftime/(double)MILLION);
    return 0;
}


 
처음 설정 시간: 1000000초.000000
남은시간      : 999999초.800000
The function_to_time took 200000 microseconds or 0.200000 seconds.

@.@

sangwoo의 이미지

먼저, usleep(1000)한 시간은 타이머 감소에 포함되지 않습니다. 타이머타입을 ITIMER_VIRTUAL로 설정하셨기 때문이지요.
설정값보다 남은 타이머의 값이 더 크게 나온 것은 setitimer()/getitimer() 구현의 버그이거나, 아니면 어떤 이유가 있기 때문이 아닐까 싶습니다. 가령 (약간 오버성이 있습니다만) 함수 실행 시간을 보정해 준다는 명목으로 setitimer시에 틱 하나정도 증가시켜서 타이머를 저장하는 거 같습니다. do_setitimer의 소스를 찾아보니 ITIMER_VIRTUAL의 경우와 ITIMER_PROF의 경우는 it_value의 값에다 틱 하나만큼 붙여서 저장하는 거 같네요. (j++) (2.6.11기준입니다.)

int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
{
        register unsigned long i, j;
        int k;

        i = timeval_to_jiffies(&value->it_interval);
        j = timeval_to_jiffies(&value->it_value);
        if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
                return k;
        switch (which) {
                case ITIMER_REAL:
                        del_timer_sync(&current->real_timer);
                        current->it_real_value = j;
                        current->it_real_incr = i;
                        if (!j)
                                break;
                        if (j > (unsigned long) LONG_MAX)
                                j = LONG_MAX;
                        i = j + jiffies;
                        current->real_timer.expires = i;
                        add_timer(&current->real_timer);
                        break;
                case ITIMER_VIRTUAL:
                        if (j)
                                j++;
                        current->it_virt_value = j;
                        current->it_virt_incr = i;
                        break;
                case ITIMER_PROF:
                        if (j)
                                j++;
                        current->it_prof_value = j;
                        current->it_prof_incr = i;
                        break;
                default:
                        return -EINVAL;
        }
        return 0;
}

이게 옳은 건지, 옳지 않은 건지는 잘 모르겠습니다. 어쨌든 실수는 아니고, 의도된 것은 분명한 것 같습니다. :-)
FreeBSD 7-CURRENT에서는, 다음과 같은 결과가 나옵니다. (효과를 확실히 보기 위해 i < 1000인 동안 loop을 실행시켰습니다.)

.............................................................. 
남은시간      : 001000초.000000
The function_to_time took 0 microseconds or 0.000000 seconds.

덧. 위에 글을 쓰셨네요. :-) ITIMER_VIRTUAL의 경우는 프로세스가 RUNNING상태일때만 timer를 감소시키므로 sleep()한 시간은 포함이 되지 않는 것입니다.

두번째 덧글. 루프를 10000번 정도 실행시키니까 시간의 감소가 보입니다. 물론 usleep(1000)은 빼고 실행시키시는 편이 시간을 절약하실 수 있겠습니다. :-)

----
Let's shut up and code.

shamlock의 이미지

getitimer할때 처음 설정값보다 더 크면 별도의 처리를 해줬으면 좋겠는데..
커널 개발자분들이 이정도를 예상하지 못했다는게..좀 납득이 안되네요
마이크로 초 단위의 타이머로는 부족한 점이 있네요

@.@

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.