Почему nanosleep () и usleep () слишком медленные? - PullRequest
3 голосов
/ 27 мая 2010

У меня есть программа, которая генерирует пакеты для отправки получателю. Мне нужен эффективный метод введения небольшой задержки между отправкой каждого пакета, чтобы не переполнить приемник. Я пробовал usleep () и nanosleep (), но они кажутся слишком медленными. Я реализовал напряженный цикл ожидания и добился большего успеха, но я знаю, что это не самый эффективный метод. Меня интересует чей-либо опыт в попытках сделать то, что я делаю. Находят ли другие функции usleep () и nanosleep () хорошо работающими для приложений такого типа?

Спасибо

Дэнни Ллеваллин

Ответы [ 5 ]

9 голосов
/ 27 мая 2010

Поведение спящих функций в течение очень малых интервалов сильно зависит от версии и конфигурации ядра.

Если у вас ядро ​​"tickless" (CONFIG_NO_HZ) и таймеры высокого разрешения, вы можете ожидать, что сны будут достаточно близки к тому, что вы просите.

В противном случае, вы, как правило, в конечном итоге будете спать на гранулярности прерывания по таймеру. Интервал прерывания таймера настраивается (CONFIG_HZ) - наиболее распространенными являются 10 мс, 4 мс, 3,3 мс и 1 мс.

2 голосов
/ 27 мая 2010

Если предположить, что подходы более высокого уровня, о которых упоминали другие комментаторы, вам недоступны, то общий подход в области встроенных / микроконтроллеров состоит в создании NOP-цикла необходимой длины.

A NOP операция занимает один цикл ЦП, и во встроенной среде вы обычно точно знаете, на какой тактовой частоте работает ваш процессор, поэтому вы можете просто использовать простое объединение циклов _NOP() или, если требуется очень короткая задержка, тогда не заморачивайтесь с циклом, просто добавьте необходимое количество nops.

regTX = 0xFF;  // Transmit FF on special register

// Wait three clock cycles
_NOP();
_NOP();
_NOP();

regTX = 0x00; // Transmit 00
2 голосов
/ 27 мая 2010

Это похоже на плохой дизайн. В идеале получатель должен ставить в очередь любые дополнительные данные, которые он получает, а затем выполнять обработку сообщений в отдельном потоке. Таким образом, он может обрабатывать пакеты данных, не полагаясь на отправителя для регулирования своих запросов.

Но, возможно, такой подход нецелесообразен, если (например) у вас нет контроля над кодом получателя или если это встроенное приложение.

0 голосов
/ 27 июня 2011

Я могу говорить о Solaris здесь, поскольку он использует таймер ОС для пробуждения спящих вызовов. По умолчанию минимальное время ожидания будет 10 мс, независимо от того, что вы указали в usleep. Однако вы можете использовать параметры hires_tick = 1 (1 мс пробуждения) и hires_hz = в файле конфигурации /etc/system, чтобы увеличить частоту вызовов по таймеру.

0 голосов
/ 27 мая 2010

Вместо того, чтобы делать что-то на уровне пакетов, где вам нужно беспокоиться о таких вещах, как превышение скорости приемника. Почему бы не использовать поток TCP для передачи данных? Пусть TCP обрабатывает такие вещи, как управление скоростью потока и повторная передача пакета.

Если вы уже вложили много средств в пакетный подход, вы всегда можете использовать слой поверх TCP для извлечения исходных пакетов данных из потока TCP и передачи их в существующие функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...