Приоритет модулей ядра и потоков SCHED_RR - PullRequest
7 голосов
/ 06 октября 2011

У меня есть встроенная платформа Linux (Beagleboard, работающая под управлением Angstrom Linux) с двумя подключенными устройствами:

  • Лазерный дальномер (Hokuyo UTM 30), подключенный через USB
  • пользовательская внешняя плата, подключенная через SPI

У нас написан модуль ядра Linux, который отвечает за передачу данных SPI. Он имеет обработчик IRQ, в котором вызывается spi_async , что в свою очередь вызывает асинхронный метод обратного вызова.

Мое приложение на C ++ состоит из трех потоков:

  • основной поток для обработки данных
  • нить для лазерного опроса
  • поток опроса SPI

У меня возникли проблемы, которые, по-видимому, вызваны взаимодействием описанных выше модулей.

  • Когда я выключаю устройство USB (лазерный дальномер), я получаю все сообщения SPI правильно (1 сообщение каждые 3 мс, длина сообщения, деленная на скорость передачи данных <1 мс), независимо от планирования потока </li>
  • Когда я включаю устройство USB и запускаю свою программу с обычным планированием потоков (SCHED_OTHER, приоритет 0, не установлен хороший уровень), около 1% сообщений «теряется», потому что метод обратного вызова spi_async выполняется, когда следующий IRQ (я мог бы обработать этот случай по-другому, чтобы не потерять сообщения, так что это не большая проблема.)
  • При включенном устройстве USB и запуске программы с SCHED_RR и

    • приоритет = 10 для основного потока
    • приоритет = 10 для потока чтения SPI
    • приоритет = 4 для потока USB / лазерного опроса

    тогда я теряю 40% сообщений, потому что IRQ снова запускается до вызова метода spi-callback! (Возможно, я все еще могу найти обходной путь, но проблема в том, что мне нужно быстрое время отклика, которого в этом случае уже нельзя достичь). Мне нужно использовать планирование потоков и лазерное устройство, поэтому я ищу способ решить этот случай.

Вопрос 1:

Я предполагал, что обработчики IRQ и обратные вызовы, запускаемые spi_async в пространстве ядра, имеют более высокий приоритет, чем любой поток, работающий в пространстве пользователя (независимо от того, является ли SCHED_RR или SCHED_OTHER). Это означало бы, что обращение к SCHED_RR в моем приложении не должно замедлять передачу SPI, но это кажется очень неправильным. Это так?

Вопрос 2:

Как я могу определить, что здесь происходит? Какие средства отладки существуют? (Или, может быть, вам не нужна дополнительная информация?) Главный вопрос для меня: почему я испытываю проблемы только при включенном лазерном устройстве. Может ли драйвер USB занимать так много времени?

----- РЕДАКТИРОВАТЬ:

Я сделал следующее наблюдение:

Обратный вызов spi_async вызывает wake_up_interruptible(&mydata->readq);wait_queue_head_t readq;). Из пользовательского пространства (моего приложения) я вызываю функцию, которая приводит к poll_wait(file, &mydata->readq, wait); Когда опрос возвращает пользовательское пространство, вызывает read().

  • Когда мое приложение работает с SCHED_OTHER, я вижу, что метод обратного вызова сначала завершается до того, как в моем модуле ядра введен метод read().
  • Когда мое приложение запускается с SCHED_RR, чтение вводится до выхода из обратного вызова.

Это кажется доказательством того, что приоритет потоков пространства пользователя выше, чем приоритет контекста метода обратного вызова. Есть ли способ изменить это поведение, и у меня все еще есть SCHED_RR для потоков моего приложения?

1 Ответ

1 голос
/ 06 октября 2011

Не все потоки ядра имеют приоритет RT. Представьте себе, что периодически просыпается поток, которому нужно выполнить некоторую фоновую работу. Вы не хотите, чтобы эта ветка предопределяла вашу ветку RT. Поэтому я думаю, что ваше первое предположение неверно.

На основе ваших других вопросов:

  • ваш основной цикл обработки получает данные SPI через очередь
  • поток обработки spi передает основную очередь обработки

Кажется, ваш основной поток обработки мешает потоку драйвера spi, отвечающему за передачу данных spi.

Вот что происходит:

  • IRQ запущен
  • вызывается spi_async, что означает, что передача данных ставится в очередь, которая будет подхвачена потоком, созданным главным драйвером spi.
  • Главный поток spi конкурирует с вашим основным потоком обработки, потоком лазера, но этот поток ядра не имеет приоритета RT, поэтому он теряет всякий раз при запуске одного из потоков RR.

Что вы можете сделать, так это вернуться к обычному планированию, одновременно играя с различными опциями CONFIG_PREEMPT_. Или связывайтесь с драйвером spi master, чтобы гарантировать, что любая отложенная работа ставится в очередь с достаточным приоритетом. Или даже не в очереди.

...