Реализация правильной межмодульной синхронизации в ядре Linux - PullRequest
7 голосов
/ 02 апреля 2012

Я реализую собственный драйвер последовательной шины для определенной платы Linux на базе ARM (собственно, пользовательский драйвер UART). Этот драйвер должен обеспечивать связь с определенным MCU на другом конце шины через специальный протокол. Драйвер не будет (и на самом деле не должен ) предоставлять какие-либо свои функции пользовательскому пространству, и его вообще невозможно будет реализовать в пользовательском пространстве (следовательно, для использования нестандартного драйвера вместо использования исходного кода). Подсистема TTY).

Драйвер реализует протокол связи, а UART выполняет чтение / запись, и ему необходимо экспортировать набор функций более высокого уровня своим пользователям, чтобы они могли общаться с MCU (например, read_register(), drive_gpios(), все эта штука). В этом модуле будет только один пользователь.

Вызывающему модулю придется ждать завершения операций (вышеупомянутые read_register() и другие). В настоящее время я рассматриваю возможность использования семафоров: пользовательский модуль вызовет функцию моего драйвера, которая будет инициировать передачи и ожидать семафор; обработчик IRQ моего драйвера будет отправлять запросы в MCU и читать ответы, а после этого отправлять сообщения на семафор, вызывая тем самым вызывающий модуль. Но я не очень знаком с программированием ядра, и меня сбивает с толку множество возможных альтернативных реализаций (тасклетов? Очереди ожидания?).

Вопрос в следующем: мой подход на основе семафоров в порядке или слишком наивен? Каковы возможные альтернативы? Есть ли какие-то подводные камни, которые я могу пропустить?

1 Ответ

5 голосов
/ 02 апреля 2012

Традиционно обработка IRQ в Linux состоит из двух частей:

  1. Так называемая «верхняя половина» фактически работает в контексте IRQ (сам обработчик IRQ). Эта часть должна выйти как можно быстрее. Таким образом, он в основном проверяет источник прерывания, а затем начинает нижнюю половину.

  2. "Нижняя половина". Это может быть реализовано как рабочая очередь. Это где фактическая работа сделана. Он работает в нормальном контексте, поэтому он может использовать функции блокировки и т. Д.

Если вы хотите только ждать IRQ в вашем рабочем потоке, лучше использовать специальный объект с именем completion. Он создан именно для этой задачи.

...