2 ответов:
An
ioctl, что означает "управление вводом-выводом" -это своего рода системный вызов для конкретного устройства. В Linux есть только несколько системных вызовов (300-400), которых недостаточно для выражения всех уникальных функций, которые могут иметь устройства. Таким образом, драйвер может определить ioctl, который позволяет приложению пользовательского пространства отправлять ему заказы. Однако ioctls не очень гибки и, как правило, немного загромождаются (десятки "магических чисел", которые просто работают... или нет), а также может быть небезопасным, поскольку вы передаете буфер в плохая обработка ядра может легко сломать вещи.альтернативой является
sysfsинтерфейс, где вы создали файл под/sys/и читать / писать, чтобы получить информацию от и к водителю. Пример того, как это настроить:static ssize_t mydrvr_version_show(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%s\n", DRIVER_RELEASE); } static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL);и во время установки драйвера:
device_create_file(dev, &dev_attr_version);тогда у вас будет файл для вашего устройства в
/sys/, например,/sys/block/myblk/versionдля драйвера блока.другой метод для более тяжелого использования-netlink, который является IPC (межпроцессная связь) метод для разговора с вашим драйвером через интерфейс сокета BSD. Это используется, например, драйверами WiFi. Затем вы связываетесь с ним из пользовательского пространства, используя
libnlилиlibnl3библиотеки.
ioctlфункция полезна, когда один реализует драйвер устройства для установки конфигурации на устройстве. например, принтер имеет параметры конфигурации для проверки и установки шрифта, размера шрифта и т. д.ioctlможет использоваться для получения текущего шрифта, а также установить шрифт на другой. В пользовательском приложении используйтеioctlчтобы отправить код на принтер, сообщая ему, чтобы вернуть текущий шрифт или установить шрифт на новый.int ioctl(int fd, int request, ...)
fdэто файловый дескриптор, тот самый вернулся с открытияrequestзапрос кода. например, GETFONT получит текущий шрифт из принтера, SETFONT установит шрифт на принтере.- третий аргумент
void *. В зависимости от второго аргумента, третий может присутствовать или не присутствовать. например, если второй аргумент SETFONT, третий аргумент может дать имя шрифта как ARIAL.Итак, теперь int-запрос-это не просто макрос, он необходим для создания кода запроса, который будет использоваться пользовательским приложением и драйвером устройства модуль для определения конфигурации устройства, с которой необходимо играть. Один отправляет код запроса с помощью
ioctlиз приложения пользователя, а затем использует код запроса в модуле драйвера устройства, чтобы определить, какое действие выполнять.код запроса состоит из 4 основных частей
1. A Magic number - 8 bits 2. A sequence number - 8 bits 3. Argument type (typically 14 bits), if any. 4. Direction of data transfer (2 bits).если код запроса SETFONT для установки шрифта на принтере, направление для передачи данных будет от пользовательского приложения к модулю драйвера устройства. Пользователь отправляет имя шрифта Arial на принтер. Если запрос код GETFONT, направление от принтера к пользовательскому приложению.
для генерации кода запроса Linux предоставляет некоторые предопределенные функции, такие как макросы.
1.
_IO(MAGIC, SEQ_NO)оба 8 бит, от 0 до 255, например, скажем, мы хотим приостановить принтер. Для этого не требуется передача adata. Поэтому мы будем генерировать код запроса, как показано ниже#define PRIN_MAGIC 'P' #define NUM 0 #define PAUSE_PRIN __IO(PRIN_MAGIC, NUM)теперь использовать
ioctlкакret_val = ioctl(fd, PAUSE_PRIN);соответствуя системный вызов в модуле водителя получит код и приостановит принтер.
__IOW(MAGIC, SEQ_NO, TYPE)MAGICиSEQ_NOтакие же, как и выше, но третья часть дает тип следующего аргумента, вспомните третий аргументioctlиvoid *. W in__IOWуказывает, что направление данных от пользовательского приложения к модулю водителя. Давайте возьмем пример, Предположим, что один говорит принтеру установить шрифт на Arial.#define PRIN_MAGIC 'S' #define SEQ_NO 1 #define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)далее
char *font = "Arial"; ret_val = ioctl(fd, SETFONT, font);теперь
fontявляется указателем, что означает его является ли адрес лучше всего представлен какunsigned long, следовательно, третья часть_IOWупоминает тип как таковой. Кроме того, этот адрес шрифта передается соответствующему системному вызову, реализованному в модуле драйвера устройства какunsigned longи нам нужно привести его к правильному типу, прежде чем использовать его. Пространство ядра может получить доступ к пользовательскому пространству и, следовательно, это работает. другие две функции, такие как макросы являются__IOR(MAGIC, SEQ_NO, TYPE)и__IORW(MAGIC, SEQ_NO, TYPE)где направление потока данных из ядра в пространство пользователя и пространство в обе стороны соответственно.пожалуйста, дайте мне знать, если это помогает!
Comments