2016-03-16 10 views
6

Pracuję na systemie z wbudowanym systemem Linux. Próbuję uzyskać znacznik czasu pakietu ze strumienia, który odbieram na gnieździe.Uzyskaj sygnaturę czasową pakietu przez wywołanie ioctl na deskryptorze pliku gniazda

Po utworzeniu gniazda, to należy wykonać następujące czynności:

if (fd != -1) { 
    int enabled = 1; 
    setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &enabled, sizeof(enabled); 
} 

Potem wiążą gnieździe, gniazdo jest typu SOCK_STREAM. Pomyślnie odbieram dane na gnieździe, dzwoniąc do funkcji recv(fd, buf, size, 0). Teraz w celu uzyskania znacznika czasu odebranych danych, Obecnie próbuję następujący:

ret = recv(fd, buf, size, 0); 
if (ret > 0) { 
    struct timeval tv_ioctl; 
    tv_ioctl.tv_sec = 0; 
    tv_ioctl.tv_usec = 0; 
    int error = ioctl(fd, SO_TIMESTAMP, &tv_ioctl); 
    printf("%ld.%ld - error = %d", (long int)tv_ioctl.tv_sec, 
      (long int)tv_ioctl.tv_usec, error); 
} 

wyjściu instrukcji printf zawsze jest następujący:

0,0 błędu = - 1

błąd = 1 oznacza, że ​​wywołanie ioctl nie powiodło się. Przeprowadziłem test z getsockopt, aby sprawdzić, czy ustawiono opcję SO_TIMESTAMP, getsockopt zwraca 0 dla opcji SO_TIMESTAMP, więc wydaje się poprawnie ustawione. Jestem trochę zagubiony, jak mogę dalej badać, dlaczego wywołanie ioctl wydaje się być nieskuteczne?

+1

Patrząc na [TO] (https://vilimpoc.org/research/ku-latency/), wydaje się, że 'SO_TIMESTAMP' służy do ustawienia opcji, a nie do pobierania danych. Aby uzyskać informacje, musisz użyć [recvmsg] (http://linux.die.net/man/2/recvmsg). – LPs

+0

Gdy pojawi się błąd z wywołania systemowego, powinieneś wydrukować 'errno' lub' strerror() 'lub użyć' perror() ', aby zrobić to za Ciebie. Jak już odkryłeś, -1 nie mówi ci nic przydatnego. – EJP

Odpowiedz

4

Ioctl do pobrania najnowszego znacznika czasu na gnieździe to SIOCGSTAMP; SO_TIMESTAMP to opcja gniazda, a nie ioctl. Kod powinien brzmieć:

int error = ioctl(fd, SIOCGSTAMP, &tv_ioctl); 
         ^^^^^^^^^^ 

Alternatywna metoda pobierania znaczników czasu jest zmiana recv do recvmmsg i wyodrębnić datownik z danych pomocniczych. Jest to bardziej wydajne, ponieważ obejmuje mniej wywołań systemowych (Socket reading and timestamps); ioctl jest jednak prostszy.

Zauważ, że SIOCGSTAMP i SO_TIMESTAMP wzajemnie się wykluczają - jeśli masz zamiar używać SIOCGSTAMP powinien wyłączyć SO_TIMESTAMP (z enabled = 0) ty. Wynika to z tego, że SO_TIMESTAMP kieruje jądrem, aby udostępnić znacznik czasu za pośrednictwem pomocniczych danych zamiast przez SIOCGSTAMP.

+0

Próbuję to teraz z SIOCGSTAMP, ustawiłem opcję SO_TIMESTAMP na 0 z setsockopt. Jednak wywołanie ioctl nadal zwraca -1. Czy muszę włączyć SIOCGSTAMP, czy może to nie jest obsługiwane przez sterownik urządzenia? – Gio

+0

@Gio czym jest ustawienie 'errno'? Jedynym powodem, dla którego zdaję sobie sprawę, że SIOCGSTAMP zawiodłoby jest to, że SO_TIMESTAMP jest włączony, w takim przypadku byłby ustawiony na ENOENT. – ecatmur

+0

'printf ("% s ", strerror (errno))' drukuje "Brak takiego pliku lub katalogu". – Gio

Powiązane problemy