Получение пакетов сокетов RAW с точностью до микросекунд
Я пишу код, который получает необработанные пакеты ethernet (без TCP/UDP) каждые 1 мс с сервера. Для каждого полученного пакета мое приложение должно ответить 14 необработанными пакетами. Если сервер не получает 14 пакетов до того, как он отправит пакет, запланированный на каждые 1 мс, тогда сервер вызывает тревогу, и приложение должно выйти из строя. Связь между сервером и клиентом - это одна к одной ссылке.
Сервер - это аппаратное обеспечение (FPGA), которое генерирует пакеты с точным интервалом 1 мс. Клиентское приложение работает на Linux (RHEL/Centos 7) с 10G SolarFlare NIC.
Моя первая версия кода похожа на эту
while(1)
{
while(1)
{
numbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
if(numbytes > 0)
{
//Some more lines here, to read packet number
break;
}
}
for (i=0;i<14;i++)
{
if (sendto(sockfd,(void *)(sym) , sizeof(sym), 0, NULL, NULL) < 0)
perror("Send failed\n");
}
}
Я измеряю время приема, беря отметки времени (используя clock_gettime
) перед вызовом recvfrom
и один за ним, я печатаю разницу во времени этих временных меток и печатаю их каждый раз, когда разница во времени превышает допустимый диапазон 900-1100 нас.
Проблема, с которой я сталкиваюсь, заключается в том, что время приема пакета колеблется. Что-то вроде этого (отпечатки находятся в микросекундах)
Decode Time : 1234
Decode Time : 762
Decode Time : 1593
Decode Time : 406
Decode Time : 1703
Decode Time : 257
Decode Time : 1493
Decode Time : 514
and so on..
И иногда время декодирования превышает 2000us, и приложение будет ломаться.
В этой ситуации приложение будет прерываться от 2 секунд до нескольких минут.
Параметры, которые я использовал до сих пор.
- Настройка близости к изолированному ядру.
- Настройка приоритетов планирования с максимальным значением с помощью
SCHED_FIFO
- Увеличение размеров буфера сокетов
- Настройка сетевого интерфейса прерывает сродство к тому же ядру, которое обрабатывает приложение
- Скручивание
recvfrom
с помощью вызовов poll(),select()
.
Все эти параметры дают значительное улучшение по сравнению с исходной версией кода. Теперь приложение будет работать в течение ~ 1-2 часов. Но этого все еще недостаточно.
Несколько наблюдений:
- Я получаю огромный дамп этих отпечатков времени декодирования, когда я принимаю ssh-сессии на Linux-машине во время работы приложения (что заставляет меня думать, что сетевая связь через другой интерфейс Ethernet 1G создает помехи для интерфейса Ethernet 10G).
- Приложение работает лучше в RHEL (время работы около 2-3 часов), чем Centos (время работы около 30 минут - 1,5 часа)
- Время выполнения также зависит от машин Linux с различными конфигурациями оборудования с той же ОС.
Просьба указать, есть ли какие-либо другие способы улучшения времени выполнения приложения.
Спасибо заранее.
Ответы
Ответ 1
Во-первых, вам необходимо проверить точность метода timestamping; clock_gettime. Разрешение - наносекунды, но точность и точность под вопросом. Это не ответ на вашу проблему, но информирует о том, насколько надежна отметка времени перед продолжением. См. Разница между CLOCK_REALTIME и CLOCK_MONOTONIC? за то, почему CLOCK_MONOTONIC следует использовать для вашего приложения.
Я подозреваю, что большинство флуктуаций времени декодирования происходит либо из-за переменного количества операций на каждый декодирование, контекстного переключения операционной системы, либо из-за прерываний.
Операции для каждого декодирования Я не могу комментировать, поскольку код был упрощен в вашем сообщении. Эта проблема также может быть профилирована и проверена.
Контекстное переключение на процесс может быть легко проверено и контролироваться https://unix.stackexchange.com/a/84345
Как заявил Рон, это очень строгие требования времени для сети. Это должна быть изолированная сеть и единая цель. Ваше наблюдение за временем перекодировки, когда ssh'ing указывает на весь другой трафик, должно быть предотвращено. Это вызывает беспокойство, учитывая отдельные сетевые адаптеры. Таким образом, я подозреваю, что проблема IRQ. См. /Proc/interrupts.
Для достижения согласованного времени декодирования в течение длинных интервалов (часов- > дней) потребуется значительно упростить ОС. Удаление ненужных процессов и сервисов, оборудования и, возможно, создание собственного ядра. Все для уменьшения переключения контекста и прерываний. В этот момент следует рассмотреть ОС реального времени. Это только улучшит вероятность согласованного времени декодирования, а не гарантирует.
Моя работа заключается в разработке системы сбора данных, которая представляет собой комбинацию АЦП с ПЛИС, ПК и ethernet. Неизбежно, несогласованность многоцелевого ПК означает, что некоторые функции должны быть перенесены на выделенное оборудование. Рассмотрите преимущества/недостатки разработки вашего приложения для ПК и переноса его на аппаратное обеспечение.