У меня есть небольшая программа, работающая на Linux (на встроенном ПК с двухъядерным процессором Intel Atom 1.6GHz с Debian 6, работающим под управлением Linux 2.6.32-5), который обменивается данными с внешним оборудованием через FTDI USB-to-serial converter ( используя модуль ядра ftdi_sio
и устройство /dev/ttyUSB*
). По существу, в моем основном цикле я запускаю
-
clock_gettime()
с помощьюCLOCK_MONOTONIC
-
select()
с таймаутом 8 мс -
clock_gettime()
как раньше - Вывести разницу во времени двух вызовов
clock_gettime()
Чтобы иметь некоторый уровень "мягких" гарантий реального времени, этот поток работает как SCHED_FIFO
с максимальным приоритетом (отображается как "RT" в top
). Это единственный поток в системе, работающий в этом приоритете, ни один другой процесс не имеет таких приоритетов. Мой процесс имеет еще один поток SCHED_FIFO
с более низким приоритетом, а все остальное - в SCHED_OTHER
. Два потока "реального времени" не связаны с ЦП и очень мало отличаются от ожидания ввода-вывода и передачи данных.
Ядро, которое я использую, не имеет патчей RT_PREEMPT (я могу переключиться на этот патч в будущем). Я знаю, что если я хочу "правильного" реального времени, мне нужно переключиться на RT_PREEMPT или, лучше, Xenomai или тому подобное. Но тем не менее я хотел бы знать, что стоит за следующими временными аномалиями в ядре "vanilla":
- Примерно 0,03% всех вызовов
select()
рассчитаны на более 10 мс (помните, что время ожидания составляло 8 мс). - Три худших случая (из более чем 12 миллионов вызовов) составили 31,7 мс, 46,8 мс и 64,4 мс.
- Все вышесказанное произошло в течение 20 секунд друг от друга, и я думаю, что какое-то задание cron могло мешать (хотя системные журналы имеют низкую информацию, кроме того, что в то время выполнялся
cron.daily
).
Итак, мой вопрос: какие факторы могут быть задействованы в таких крайних случаях? Это то, что может произойти внутри самого ядра Linux, т.е. Я должен переключиться на RT_PREEMPT или даже на не-USB-интерфейс и Xenomai, чтобы получить более надежные гарантии? Может ли /proc/sys/kernel/sched_rt_runtime_us
укусить меня? Есть ли другие факторы, которые я, возможно, пропустил?
Еще один способ поставить этот вопрос: что еще я могу сделать, чтобы уменьшить эти аномалии задержки, не переключаясь на "более сложную" среду реального времени?
Обновление. Я наблюдал новый "худший худший случай" около 118,4 мс (один раз в общей сложности около 25 миллионов вызовов select()
). Даже когда я не использую ядро с каким-либо расширением в реальном времени, меня несколько беспокоит то, что крайний срок может быть пропущен более чем на одну десятую секунды.