Подготовка драйверов устройств для Real-Time Linux

На конференции Embedded Linux 2018 Джулия Картрайт из NI рассказала авторам драйверов устройств, как обеспечить бесперебойную работу их драйверов в Real-Time Linux.

Хотя Real-Time Linux (RT Linux) на протяжении многих лет был одним из основных продуктов на конференциях по встраиваемым Linux-системам - вот история презентаций RT в 2007 году - многие разработчики считают эту технологию периферийной по отношению к своим собственным встраиваемым проектам.
Тем не менее, поскольку RT, включенная через патч PREEMPT_RT, готовится к полной интеграции в основное ядро, более широкому кругу разработчиков следует обратить внимание.
В частности, авторам драйверов устройств Linux необходимо убедиться, что их драйверы хорошо работают с ядрами с поддержкой RT.

На недавней конференции по встроенному Linux в Портленде инженер по программному обеспечению National Instruments Джулия Картрайт, исполняющая обязанности стабильного выпуска исправления RT, выступила с хорошо посещаемой презентацией под названием «Что должен знать каждый разработчик драйверов о RT». Картрайт начал с обзор RT, который помогает обеспечить гарантии выполнения пользовательских задач для встроенных приложений, требующих высокого уровня детерминизма.
Затем она описала классы проблем, связанных с драйверами, которые могут оказать пагубное влияние на RT, а также возможные решения.


Джулия Картрайт объясняет, как RT Linux использует прокладки для уменьшения задержки irq_dispatch

(щелкните изображение, чтобы увеличить)

Одна из проблем любой операционной системы реального времени состоит в том, что у большинства целевых приложений есть два типа задач: задачи с требованиями в реальном времени и чувствительностью к задержке, и задачи для не критичных ко времени задач, таких как мониторинг диска, пропускная способность или I / О.
«Два класса задач должны выполняться вместе и, возможно, взаимодействовать друг с другом со смешанной критичностью», - пояснил Картрайт.
«Вы должны разрешить две разные степени чувствительности ко времени».

Одним из решений является разделение задач с использованием двух разных аппаратных платформ.
«У вас может быть плата на базе Arm Cortex-R, FPGA или PLD для сверх срочных задач, а затем плата серии Cortex-A с Linux», - сказал Картрайт.
«Это обеспечивает лучшую изоляцию, но повышает затраты на единицу, и между доменами сложно общаться».

Другой подход заключается в использовании подхода виртуализации, предоставляемого Xenomai , другим основным решением на основе Linux, кроме PREEMPT_RT.
«Xenomai использует гипервизор, совместный подход с использованием гипервизора или решения AMP для отделения ОСРВ от Linux», - сказал Картрайт.
«Тем не менее, между двумя системами все еще существует компромисс между ограниченными связями».

PREEMPT_RT RT Linux позволяет обеим системам совместно использовать ядро, планировщик, стек устройств и подсистемы.
Кроме того, механизмы Linux IPC могут использоваться для связи между ними.
«Там не так много изоляции, но гораздо больше общения и удобства использования», сказал Картрайт.

Одна из проблем с RT заключается в том, что «поскольку драйверы распределяются между системами реального и не реального времени, они могут плохо себя вести», - сказал Картрайт.
«Многие ошибки, которые мы находим в RT, связаны с драйверами устройств».

В RT время между тем, когда происходит событие, например таймер, запускающий прерывание, или устройством ввода-вывода, запрашивающим услугу, и временем, когда выполняется задача реального времени, называется дельтой.
«Системы RT пытаются охарактеризовать и связать это каким-то осмысленным образом», - пояснил Картрайт.
«Циклический тест берет метку времени, затем спит в течение установленного времени, такого как 10 мс, а затем берет метку времени, когда поток просыпается.
Разница между временными метками, которая составляет количество времени, в течение которого нить спала, называется дельтой ».

Эта дельта может быть разбита на две фазы.
Первым является irq_dispatch, который представляет собой время, которое проходит между аппаратным запуском и отправкой до момента, пока планировщик потока не проинструктирован о том, что поток должен работать.
Второй этап - это задержка планирования, то есть время между тем, когда планировщик узнал, что задача с высоким приоритетом должна быть запущена до того момента, когда процессору будет дано задание для выполнения.

irq_dispatch latency

При использовании основного Linux без расширений RT задержка irq_dispatch может быть значительной.
«Скажем, у вас есть один поток, выполняющийся в пользовательском режиме, и запускается внешнее прерывание, такое как сетевое событие, которое вас не волнует в приложении реального времени», - сказал Картрайт.
«Но процессор собирается преобразовать его в контекст жесткого прерывания и начать выполнение обработчика, связанного с этим сетевым устройством.
Если в течение этой длительности обработчика прерываний происходит событие с высоким приоритетом, его нельзя запланировать на ЦП, пока не будет выполнено прерывание с низким приоритетом ».

Дельта между срабатыванием внутреннего события и внешним событием «напрямую влияет на задержку irq_dispatch», - сказал Картрайт.
«Без RT-патча было бы беспорядочно определять границы для этого, потому что граница была бы границей самого длинного работающего обработчика прерываний в системе».

RT избегает этой задержки, форсируя потоки irq.
«Существует очень мало кода, который мы выполняем в контексте жесткого прерывания, - только небольшие шайбы, которые пробуждают потоки, которые будут выполнять ваш обработчик», - сказал Картрайт.
«У вас может быть запущена задача с низким приоритетом и, возможно, также задача со средним приоритетом, которую запускает irq, но только небольшая часть времени уходит на пробуждение связанных обработчиков для потоков».

RT также предоставляет другие гарантии.
Например, поскольку обработчики прерываний теперь выполняются в потоке, это может быть прервано.
«Если срабатывает высокоприоритетное критическое прерывание в реальном времени, этот поток можно запланировать немедленно, что снижает задержку irq_dispatch», - сказал Картрайт.

Картрайт сказал, что большинству драйверов не требуется никаких модификаций для участия в принудительной потоковой обработке IRQ.
На самом деле, «поток irq фактически существует в mainline сейчас.
Вы можете загрузить ядро ​​и передать параметр потока irq, и он будет обрабатывать все ваши прерывания.
RT добавит принудительное включение ».

Тем не менее, есть несколько случаев, когда это вызывает проблемы.
«Если ваши драйверы вызываются в процессе доставки прерывания, вы не можете быть в потоке», - сказал Картрайт.
«Это может произойти с реализациями irqchip , которые не должны быть многопоточными.
Другая проблема может возникнуть, если драйвер вызывается планировщиком ».


Юля

каретник

Другие сбои могут возникать при «явном отключении прерываний с использованием local_irq_disable или local_irq_save.
Картрайт не рекомендует использовать такие команды в драйверах.
В качестве альтернативы local_irq_disable Картрайт предложил использовать спин-блокировки или локальные блокировки, новую функцию, которая вскоре будет предложена для магистрали.
В отдельной презентации на ELC 2018 под названием « Поддержание стабильного ядра в реальном времени» разработчик ядра Linux Стивен Ростедт углубленно рассматривает локальные блокировки.

Картрайт закончила обсуждение вопросов задержки irq_dispatch, обсудив некоторые редкие, связанные с аппаратным обеспечением проблемы MMIO, которые могут возникнуть.
Однажды, когда она случайно потянула кабель Ethernet во время тестирования, это вызвало буферизацию в межсоединении, что приводило к сбоям в работе прерываний и было трудно исправить.
«Чтобы решить эту проблему, мы должны были следить за каждой записью с помощью обратного чтения, что предотвращает наложение записи», - сказала она.
Конечное решение?
«Убери наркотики от тех, кто занимается железом».

Планирование задержки

Похоже, что меньше проблем с драйверами, связанных со второй фазой задержки - планированием, - с момента, когда вы выполняете поток в реальном времени, до времени, когда запланирован поток IRQ.
Один пример проистекает из использования preempt_disable, когда предотвращает планирование потока с более высоким приоритетом по возвращении из прерывания, потому что вытеснение было отключено.

«Единственная причина, по которой драйвер устройства использует preempt_disable, заключается в том, что вам нужно синхронизироваться с самим процессом планирования, что может произойти с cpufreq и cpuidle», - сказал Картрайт.
«Вместо этого используйте локальные блокировки».

В основном Linux критические секции с защитой от блокировки неявно выполняются с отключенным вытеснением, что также может привести к проблемам с задержкой.
«С помощью RT мы решаем эту проблему, делая блокировку спин-блокировки в критических секциях», - сказал Картрайт.
«Мы превращаем их в мьютексы с поддержкой pi и отключаем миграцию.
Когда спин-блокировка удерживается потоком, она может быть вытеснена потоком с более высоким приоритетом для ввода внешней границы ».

По словам Картрайта, большинство драйверов не требуют никаких изменений для того, чтобы их критические секции могли быть вытеснены.
Однако, если драйвер участвует в диспетчере прерываний или планировании, он должен использовать raw_spin_lock (), и все критические секции должны быть минимальными и ограниченными.

Дополнительную информацию можно найти в слайд-шоу Cartwright's RT (PDF) и видео на YouTube .

Эта статья защищена авторским правом © 2018 Linux.com и была первоначально опубликована здесь .
Он был воспроизведен этим сайтом с разрешения его владельца.
Пожалуйста, посетите Linux.com для получения последних новостей и статей о Linux и open source.