При работе с UDP-сокетами в Linux (SOCK_DGRAM
) я заметил странное поведение при попытке получить метки времени приема пакетов как через ioctl(..., SIOCGSTAMP, ...)
, так и с помощью gettimeofday()
, вызываемые сразу после получения каждого пакета.
В частности, при установлении соединения между клиентом и сервером, связывающего / прослушивающего один и тот же порт, я заметил, что первый пакет всегда демонстрирует такое поведение, а все последующие - нет.
Вот наиболее важный фрагмент кода для получения метки времени получения пакета:
// Receive UDP packet with recvfrom()...
gettimeofday(&rx_timestamp_usr,NULL);
fprintf(stdout,"gettimeofday() (before ioctl()): %lu.%lu\n",rx_timestamp_usr.tv_sec,rx_timestamp_usr.tv_usec);
if(ioctl(args->sData.descriptor,SIOCGSTAMP,&rx_timestamp)==-1) {
// Print error message...
break;
}
gettimeofday(&rx_timestamp_usr,NULL);
fprintf(stdout,"gettimeofday() (after ioctl()): %lu.%lu\n",rx_timestamp_usr.tv_sec,rx_timestamp_usr.tv_usec);
fprintf(stdout,"ioctl: %lu.%lu\n",rx_timestamp.tv_sec,rx_timestamp.tv_usec);
// ...
В качестве вывода, например, при запуске, как клиента, так и сервера на интерфейсе обратной связи, я вижу что-тонапример:
gettimeofday() (before ioctl()): 1549636037.59845
gettimeofday() (after ioctl()): 1549636037.59884
ioctl: 1549636037.59882
gettimeofday() (before ioctl()): 1549636037.69922
gettimeofday() (after ioctl()): 1549636037.69959
ioctl: 1549636037.69844
gettimeofday() (before ioctl()): 1549636037.79890
gettimeofday() (after ioctl()): 1549636037.79926
ioctl: 1549636037.79811
gettimeofday() (before ioctl()): 1549636037.89888
gettimeofday() (after ioctl()): 1549636037.89924
ioctl: 1549636037.89810
gettimeofday() (before ioctl()): 1549636037.99912
gettimeofday() (after ioctl()): 1549636037.99963
ioctl: 1549636037.99759
Как видите, пакеты 2-5 показывают ожидаемое поведение, причем отметка времени ioctl
всегда предшествует любой отметке времени, полученной благодаря gettimeofday()
.
Вместо этого первый пакет возвращает значение, которое позже по времени относительно того, что я получаю благодаря первому gettimeofday()
Звоните.
Почему я замечаю это поведение?Разве SIOCGSTAMP
не возвращает метку времени пакета, как только он получен ядром?Если это так, то почему он возвращает значение, которое позже по сравнению с тем, которое приходит из gettimeofday()
, которое вызывается как минимум из 10 строк кода после recvfrom()
?