Как отправлять пакеты с задержкой 512 нс с использованием Socket Programming и UDP socket

Использование SOCK_DGRAM для UDP сокетов

Все пакеты имеют длину 22 bytes (т. Е. 64 including headers)

client.c

...
    no_of_packets--;
    sprintf(buf, "#:!0 rem");
    sprintf(buf, format , buf);
    sprintf(buf_aux, "#: 0 rem");
    sprintf(buf_aux, format , buf_aux);
    buf[MAX_LINE-1] = '\0';
    buf_aux[MAX_LINE-1] = '\0';
    len = strlen(buf) + 1;
    send(s, buf, len, 0);
    while (no_of_packets-- > 1) {
        nanosleep(&T, NULL);
        send(s, buf, len, 0);
    }
    send(s, buf_aux, len, 0);

server.c

...
while(1) {
        if (len = recv(s, buf, sizeof(buf), 0)){
            // do nothing
        }
}

Когда я открываю Wireshark, чтобы увидеть среднюю задержку между отправляемыми пакетами,

я вижу следующее:

  • МИН [задержка 118]: 0,000 006 795 с => 6 мкс

  • МАКС. задержка: 0,000 260 952 с => 260 мкс

  • Но я хочу отправлять пакеты каждые 512 нсек (т. Е. 0,512 мкс).

Как можно достичь этой скорости?

1
задан 18 September 2019 в 14:28

1 ответ

Проблема с наносном состоит в том, что он включает довольно значительные издержки. Пользователи склонны ожидать точные задержки вниз с очень низкими значениями, который не действительно практичен для ЦП, приводящего к стандартной программе сна. Ожидание - это:

actual delay = nanosleep(requested delay)

тогда как, в действительности пользователи получают это:

actual delay = nanosleep(requested delay) + the fixed overheads.

На моем тестовом компьютере, с принудительной привязкой ЦП (для удаления эффектов планировщика) и набор регулятора частотного масштабирования ЦП к производительности фиксированные издержки составляют 52 микросекунды.

Возможное решение для Вашей проблемы состоит в том, чтобы заменить вызов, чтобы наноспать с циклом задержки. Затем ЦП не уступил бы, войдя неактивный, ни подвергся бы издержкам вызова операционной системы. Конечно, цикл задержки может быть трудно калибровать для фактического получения желаемой задержки. Я сделал две программы, один наносон использования и одно использование цикла задержки для демонстрации. Для создания других издержек незначительными, сон и циклы задержки выполняются очень много раз в течение каждого раза и печатают вызовы типа:

enter image description here

Для ссылки программы использовали:

версия наносна:

/*****************************************************************************
*
* test_slp2.c 2019.09.18 Smythies
*       Create data to determine the lower limit of nanosleep.
*
* test_slp.cpp 2017.11.25 Smythies
*       Of course, none of this stuff works the way it used to.
*
* test_slp.cpp 2012.01.24 Smythies
*          I need to be able to yeild (sleep), but for less than a second.
*          Experiment with nanosleep and usleep functions.
*
*****************************************************************************/

// prevent warning about nanosleep
#define _POSIX_C_SOURCE 199309L

#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#define CR 13

unsigned long long stamp(void){
   struct timeval tv;

   gettimeofday(&tv, NULL);

   return (unsigned long long)tv.tv_sec * 1000000 + tv.tv_usec;
} /* endprocedure */

int main(){
   unsigned long long start, now;
   long i, j, k;
   int ns;
   struct timespec time;

   time.tv_sec = 0;
   start = stamp();
   for(ns = 500; ns < 100000; ns = ns + 500){
      for(j = 0; j < 100000; j++){
         time.tv_nsec = ns;
         nanosleep(&time, &time);
      } /* endfor */
      now = stamp();
      printf("%d %llu\n", ns, (now - start));
      start = now;
   } /* endfor */
   return(0);
}

И версия цикла задержки, включая сырую калибровку, которую показывает график, не является большой:

/*****************************************************************************
*
* test_slp3.c 2019.09.18 Smythies
*       Now, do the same as test_slp2, but use a waste time loop instead of
        nanosleep.
*
* test_slp2.c 2019.09.18 Smythies
*       Create data to determine the lower limit of nanosleep.
*
* test_slp.cpp 2017.11.25 Smythies
*       Of course, none of this stuff works the way it used to.
*
* test_slp.cpp 2012.01.24 Smythies
*          I need to be able to yeild (sleep), but for less than a second.
*          Experiment with nanosleep and usleep functions.
*
*****************************************************************************/

// prevent warning about nanosleep
#define _POSIX_C_SOURCE 199309L

#include <sys/time.h>
#include <sys/types.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

/* for my test computer */
#define CALIBRATION 26

unsigned long long stamp(void){
   struct timeval tv;

   gettimeofday(&tv, NULL);

   return (unsigned long long)tv.tv_sec * 1000000 + tv.tv_usec;
} /* endprocedure */

int main(){
   unsigned long long start, now;
   long i, j, k, m, loops;
   int ns;
   struct timespec time;

   time.tv_sec = 0;
   start = stamp();
   for(ns = 500; ns <= 10000; ns = ns + 100){
      loops = ns * CALIBRATION / 50;  /* will have rounding issues */
      for(m = 0; m < 10000000; m++){ /* this is just to slow things down, so we can test */
         for(j = 0; j < loops; j++){
            k = j;  /* make sure any compile optimizer doesn't take out the loop */
         } /* endfor */
      } /* endfor */
      now = stamp();
      printf("%d %llu\n", ns, (now - start));
      start = now;
   } /* endfor */
   return(0);
}

Ожидаемый вопрос: Почему никакие gettimeofday не дрожат в тесте абонентского шлейфа задержки, когда Вы (I) утверждаете, что это - причина дрожания в версии наносна? Ответ: Возможно becuase метод цикла задержки работал за намного дольше на образец, чем версия наносна. Или, я был неправ.

Привязка ЦП была вызвана для этих тестов. т.е.:

time taskset -c 3 ./test_slp3

Я синхронизировал полный тест так же, как проверку работоспособности, поскольку сумма отдельных времен должна равняться полному времени. Они сделали.

Регулятор частотного масштабирования ЦП был установлен на производительность:

$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
performance
performance
performance
performance
performance
performance
performance
performance
1
ответ дан 7 December 2019 в 14:58

Другие вопросы по тегам:

Похожие вопросы: