Доступ к платформе устройства из пространства пользователя
С общей точки зрения, я пытаюсь выяснить, как получить доступ к устройству платформы из пространства пользователя. Если быть более точным, у меня есть контроллер EMIF и SoC, который я добавил в свое дерево устройств, и я считаю, что он правильно привязан к предварительно написанному драйверу платформы EMIF. Сейчас я пытаюсь выяснить, как я могу получить доступ к этому устройству EMIF из приложения пользовательского пространства. Я натолкнулся на пару разных тем, которые, кажется, имеют какое-то отношение к этой проблеме, но я не могу понять, как они связаны.
1) Когда я читаю, кажется, что большинство операций ввода-вывода осуществляется с помощью узлов устройств, которые создаются mknod()
мне нужно создать узел устройства для доступа к этому устройству?
2) Я прочитал несколько потоков, в которых рассказывается о написании модуля ядра (Character?, Block?), Который может взаимодействовать как с пользовательским пространством, так и с драйвером устройства платформы, и использовать его в качестве посредника.
3) Я прочитал о возможности использования mmap()
отобразить память моего платформенного устройства в пространство моей виртуальной памяти. Это возможно?
4) Кажется, что когда создается экземпляр драйвера EMIF, он вызывает probe()
fucntion. Какие функции вызовет приложение пользовательского пространства в драйвере?
2 ответа
Не совсем понятно, что вам нужно сделать (и я должен предупредить, что у меня нет опыта работы с EMIF или конкретно с "платформенными устройствами"), но вот некоторый обзор, который поможет вам начать:
Да, обычный способ предоставления доступа к устройству - через узел устройства. Обычно этот доступ предоставляется драйвером символьного устройства, если только нет более специфического способа его предоставления. В большинстве случаев, если приложение говорит "напрямую" с вашим драйвером, это символьное устройство. Большинство других типов устройств используются для взаимодействия с другими подсистемами ядра: например, блочное устройство обычно используется для предоставления доступа от драйвера файловой системы (скажем) к базовому дисководу; сетевой драйвер обеспечивает доступ к сети из встроенного в стек TCP/IP ядра и т. д.
Ваш драйвер может поддерживать несколько методов или точек входа char, но наиболее распространенными являются "чтение" (т. Е. Если программа пользовательского пространства открывает ваше устройство и выполняет чтение (2) с него), "запись" (аналогично write(2)) и "ioctl" (часто используется для задач конфигурации / администрирования, которые не попадают ни в чтение, ни в запись). Обратите внимание, что mknod(2) создает только пользовательскую часть устройства. В ядре должен быть соответствующий драйвер устройства ("основной номер устройства", указанный в вызове mknod, связывает узел пользовательского пространства с драйвером).
Для фактического создания узла устройства в файловой системе это может быть автоматизировано (то есть узел автоматически отобразится в / dev), если вы вызовете правильные функции ядра при настройке устройства. Есть специальный демон, который получает уведомления от ядра и отвечает, выполняя системный вызов mknod(2).
Модуль ядра - это просто динамически загружаемый способ создания драйвера или другого расширения ядра. Он может создать символ, блок или сетевое устройство (и др.), Но также может быть статически связанный модуль. Существуют некоторые различия в возможностях в основном потому, что не все функции ядра, которые вы, возможно, захотите использовать, "экспортируются" (то есть видимы для) динамически загружаемых модулей.
Можно поддерживать отображение памяти устройства в пространство виртуальной памяти пользователя. Это будет реализовано еще одной точкой входа драйвера (mmap). Смотрите struct file_operations для всех точек входа, которые может поддерживать драйвер char.
Это в значительной степени зависит от вас: это зависит от того, что приложение должно уметь делать. В ядре много драйверов, которые не предоставляют прямой функции для пользовательского пространства, только для другого кода ядра. Что касается "проверки", то существует множество функций проверки, определенных в различных интерфейсах. В большинстве случаев они вызываются ядром (или, возможно, драйвером "класса" более высокого уровня), чтобы позволить конкретному драйверу обнаруживать, идентифицировать и "запрашивать" отдельные устройства. Они (тестовые функции) обычно не имеют ничего общего с предоставлением доступа из пользовательского пространства, но я вполне мог бы что-то упустить в определенном интерфейсе.
Вам необходимо создать узел устройства для доступа к устройству.
Функция зондирования вызывается, когда драйвер находит соответствующее устройство.
Для получения информации об API устройства на платформе могут быть полезны следующие статьи.
Платформа устройства API Платформа устройств и деревьев устройств