2014-09-29 8 views
0

나는 X 유즈 (utecs)를 실행하는 루프를 가지고 있는데, 이는 일부 I/O를 수행 한 다음 나머지 X 유즈크에 대해 잠자는 것으로 구성된다.gettimeofday()를 사용하는 자체 수정주기 타이머

long long getus() 
{ 
     struct timeval time; 
     gettimeofday(&time, NULL); 
     return (long long) (time.tv_sec + time.tv_usec); 
} 
: (약) 수면 시간을 계산하려면, 내가 뭘 모두가 I/O 전후에 타임 스탬프를 복용하고 여기 X.의 차이를 빼 내가 타임 스탬프를 위해 사용하고 기능입니다

당신이 상상할 수 있듯이, 이것은 상당히 빠르게 표류하기 시작하고 I/O 버스트 사이의 실제 시간은 대개 X보다 X 수십 ms 더 깁니다. 좀 더 정확한 결과를 얻으려면 레코드를 유지하는 것이 좋습니다. 이전주기가 시작된 시간 (이 시작 시간 소인과 이전주기 사이의 시간)을 계산할 수 있습니다. 그렇다면 X보다 얼마나 더 오래되었는지 알 수 있습니다.이주기를 위해 수면을 수정할 수 있습니다.

long long start, finish, offset, previous, remaining_usecs; 
    long long delaytime_us = 1000000; 

    /* Initialise previous timestamp as 1000000us ago*/ 
    previous = getus() - delaytime_us; 
    while(1) 
    { 
      /* starting timestamp */ 
      start = getus(); 

      /* here is where I would do some I/O */ 

      /* calculate how much to compensate */ 
      offset = (start - previous) - delaytime_us; 

      printf("(%lld - %lld) - %lld = %lld\n", 
        start, previous, delaytime_us, offset); 

      previous = start; 

      finish = getus(); 

      /* calculate to our best ability how long we spent on I/O. 
      * We'll try and compensate for its inaccuracy next time around!*/ 
      remaining_usecs = (delaytime_us - (finish - start)) - offset; 

      printf("start=%lld,finish=%lld,offset=%lld,previous=%lld\nsleeping for %lld\n", 
        start, finish, offset, previous, remaining_usecs); 

      usleep(remaining_usecs); 

    } 

루프의 첫 번째 반복 작업 것으로 보인다 상황이 엉망 그러나 이후 있음 : 여기

내가 그것을 구현하기 위해 노력하고있어 방법이다. 출력의 첫 번째 행은 이전 사이클 시간이 계산 방법을 보여

(1412452353 - 1411452348) - 1000000 = 5 
start=1412452353,finish=1412458706,offset=5,previous=1412452353 
sleeping for 993642 

(1412454788 - 1412452353) - 1000000 = -997565 
start=1412454788,finish=1412460652,offset=-997565,previous=1412454788 
sleeping for 1991701 

(1412454622 - 1412454788) - 1000000 = -1000166 
start=1412454622,finish=1412460562,offset=-1000166,previous=1412454622 
sleeping for 1994226 

(1412457040 - 1412454622) - 1000000 = -997582 
start=1412457040,finish=1412465861,offset=-997582,previous=1412457040 
sleeping for 1988761 

(1412457623 - 1412457040) - 1000000 = -999417 
start=1412457623,finish=1412463533,offset=-999417,previous=1412457623 
sleeping for 1993507 

:

여기서 루프의 5 번 반복에 대한 출력이다. 처음 두 개의 타임 스탬프는 기본적으로 1000000us 떨어져 있습니다 (1412452353 - 1411452348 = 1000005). 그러나이 후에 시작 타임 스탬프 간의 거리는 옵셋과 함께 너무 비합리적으로 보입니다. 내가 뭘 잘못하고 있는지 아는 사람 있습니까?

편집 : 정확한 타이머를 얻고 지연 중에 잠을 잘 수있는 더 좋은 방법에 대한 제안을 환영합니다.

답변

0

더 많은 조사를 한 후에 나는 여기에 잘못된 두 가지를 발견했습니다. 첫째로, 나는 잘못된 타임 스탬프를 계산하고 있습니다.

return (long long)1,000,000 *(time.tv_sec + time.tv_usec);

및 둘째, I는 unsigned long long 또는 uint64_t의 타임 스탬프를 저장한다 : getus()는 다음과 같이 반환한다. 그래서 getus()는 다음과 같아야합니다

uint64_t getus() 
{ 
     struct timeval time; 
     gettimeofday(&time, NULL); 
     return (uint64_t) 1000000 * (time.tv_sec + time.tv_usec); 
} 

실제로 내일까지이 테스트 할 수 없습니다, 그래서 다시보고합니다.