- Драйверы устройств в Linux
- Часть 5: Файлы символьных устройств – создание файлов и операции с ними
- Автоматическое создание файлов устройств
- Операции с файлами
- null — драйвер
- Подведем итог
- Подключенные устройства Linux
- Файлы устройств Linux
- Классификация файлов устройств
- Работа с устройствами в Linux
- Создание устройств в Linux
- Выводы
Драйверы устройств в Linux
Часть 5: Файлы символьных устройств – создание файлов и операции с ними
Эта статья является продолжением серии статей о драйверах устройств в Linux. В ней обсуждаются вопросы, касающиеся символьных драйверов и их реализации.
В моей предыдущей статье я упоминал, что даже при регистрации диапазона устройств , файлы устройств в директории /dev не создаются — Светлана должна была создать их вручную с помощью команды mknod . Но при дальнейшем изучении Светлана выяснила, что файлы устройств можно создавать автоматически с помощью демона udev . Она также узнала о втором шаге подключения файла устройства к драйверу устройства — связывание операций над файлом устройства с функциями драйвера устройства. Вот что она узнала.
Автоматическое создание файлов устройств
Ранее, в ядре 2.4, автоматическое создание файлов устройств выполнялось самим ядром в devfs с помощью вызова соответствующего API. Однако, по мере того, как ядро развивалось, разработчики ядра поняли, что файлы устройств больше связаны с пользовательским пространством и, следовательно, они должны быть именно там, а не в ядре. Исходя из этого принципа, теперь для рассматриваемого устройства в ядре в /sys только заполняется соответствующая информация о классе устройства и об устройстве. Затем в пользовательском пространстве эту информацию необходимо проинтерпретировать и выполнить соответствующее действие. В большинстве настольных систем Linux эту информацию собирает демон udev, и создает, соответственно, файлы устройств.
Демон udev можно с помощью его конфигурационных файлов настроить дополнительно и точно указать имена файлов устройств, права доступа к ним, их типы и т. д. Так что касается драйвера, требуется с помощью API моделей устройств Linux, объявленных в
, заполнить в /sys соответствующие записи. Все остальное делается с помощью udev . Класс устройства создается следующим образом:
Затем в этот класс информация об устройстве ( ) заносится следующим образом:
Здесь, в качестве first указывается dev_t . Соответственно, дополняющими или обратными вызовами, которые должны вызыватся в хронологически обратном порядке, являются:
Посмотрите на рис.1 на записи /sys , созданные с помощью chardrv — запись ( ) и с помощью mynull — запись ( ). Здесь также показан файл устройства, созданный с помощью udev по записи : , находящейся в файле dev .
Рис.1: Автоматическое создание файла устройства
В случае, если указаны несколько младших номеров minor, API device_create() и device_destroy() могут вызываться в цикле и в этом случае окажется полезной строка ( ). Например, вызов функции device_create() в цикле с использованием индекса i будет иметь следующий вид:
Операции с файлами
Независимо от того, что системные вызовы (или, в общем случае, операции с файлами), о которых мы рассказываем, применяются к обычным файлам, их также можно использовать и с файлами устройств. Т.е. мы можем сказать: если смотреть из пользовательского пространства, то в Linux почти все является файлами. Различие — в пространстве ядра, где виртуальная файловая система (VFS) определяет тип файла и пересылает файловые операции в соответствующий канал, например, в случае обычного файла или директория — в модуль файловой системы, или в соответствующий драйвер устройства в случае использования файла устройства. Мы будем рассматривать второй случай.
Теперь, чтобы VFS передала операции над файлом устройства в драйвер, ее следует об этом проинформировать. И это то, что называется регистрацией драйвером в VFS файловых операций. Регистрация состоит из двух этапов. (Код, указываемый в скобках, взят из кода «null -драйвера», который приведен ниже).
Во-первых, давайте занесем нужные нам файловые операции ( my_open , my_close , my_read , my_write , …) в структуру, описывающую файловые операции ( struct file_operations pugs_fops ) и ею инициализируем структуру, описывающую символьное устройство ( struct cdev c_dev ); используем для этого обращение cdev_init() .
Затем передадим эту структуру в VFS с помощью вызова cdev_add() . Обе операции cdev_init() и cdev_add() объявлены в
. Естественно, что также надо закодировать фактические операции с файлами ( my_open , my_close , my_read , my_write ).
Итак, для начала, давайте все это сделаем как можно проще — скажем, максимально просто в виде «null драйвера».
null — драйвер
Светлана повторила обычный процесс сборки, добавив при этом некоторые новые проверочные шаги, а именно:
- Собрала драйвер (файл .ko ) с помощью запуска команды make .
- Загрузила драйвер с помощью команды insmod .
- С помощью команды lsmod получила список всех загруженных модулей.
- С помощью команды cat /proc/devices . получила список используемых старших номеров major.
- Поэкспериментировала с «null драйвером» (подробности смотрите на рис.2).
- Выгрузила драйвер с помощью команды rmmod .
Рис.2: Эксперименты с «null драйвером»
Подведем итог
Светлана олпределенно была довольна; она сама написала символьный драйвер, который работает точно также, как и стандартный файл устройства /dev/null . Чтобы понять, что это значит, проверьте пару для файла /dev/null , а также выполните с ним команды echo и cat .
Но Светлану стала беспокоить одна особенность. В своем драйвере она использовала свои собственные вызовы ( my_open , my_close , my_read , my_write ), но, к удивлению, они, в отличие от любых других вызовов файловой системы, работают таким необычным образом. Что же тут необычного? Необычно, по крайней мере с точки зрения обычных файловых операций, то, что чтобы Светлана не записывала, при чтении она ничего не могла получить. Как она сможет решить эту проблему? Читайте следующую статью.
Источник
Подключенные устройства Linux
Работа с устройствами в Linux очень сильно отличается от Windows. Главная концепция Linux в том, что все есть файл, не только пользовательские файлы с информацией, но и различные настройки ядра, подключенные устройства, память, сетевые соединения, все это представлено в виде файлов, которые размещены в специальных файловых системах.
С помощью этих файлов система работает с устройствами, и вы можете ими управлять с помощью различных утилит. В этой статье мы рассмотрим как выполняется работа с устройствами Linux, что из себя представляют устройства Linux, а также рассмотрим несколько примеров создания файлов устройств и обращения к ним. Это довольно интересная тема.
Файлы устройств Linux
Все файлы устройств расположены в каталоге /dev, который есть неотделимой частью корневой файловой системы, поскольку они должны быть доступны на всех этапах загрузки. Они также известны как специальные файлы устройств. Эти файлы используются операционной системой для обеспечения пользователю и программам интерфейса доступа к устройствам, подключенным к компьютеру.
Самое важное, что нужно знать об этих файлах — это не драйверы устройств, их лучше рассматривать как интерфейс доступа к драйверам устройств. Приложение отправляет данные в файл устройства, откуда они читаются драйвером устройства и отправляются на физическое устройства. Обратная передача от физических устройств тоже проходит по этому пути через файл устройства. Давайте посмотрим как будет выглядеть поток передачи данных для типичной команды, например, cat:
На схеме приведена схема передачи данных для команды cat /etc/resolv.conf. Вы выполняете команду из терминала, утилита отправляет запрос файла драйверу, который ищет файл на диске и читает его содержимое. Данные передаются через файл устройства, а затем опять же, через файл устройства псевдо-терминала передаются в эмулятор терминала 6, где они будут отображены.
Если мы перенаправим вывод команды в файл, например, cat /etc/resolv.conf > /etc/resolv.bak, то левая часть схемы останется неизменной, а правая сторона будет вести к файлу устройства /dev/sda2. Эти устройства делают очень простым использование стандартных потоков ввода/вывода для доступа к каждому устройству. Простое перенаправление потока данных в файл устройства приведет к записи данных на устройство.
Классификация файлов устройств
Файлы устройств можно классифицировать по меньшей мере двумя способами. Первая и наиболее широкая классификация — на основе потока данных. В устройствах TTY и других символьных устройствах, данные обрабатываются по одному символу или байту за раз. В блочных устройствах, таких как жесткие диски данные передаются блоками, как правило, с размером, кратным 256 байт.
Если вы еще этого не делали, то перейдите в папку /dev/ и посмотрите список находящихся там файлов с помощью команды ls. Вы увидите очень длинный список файлов с их правами доступа, владельцами и группами — это список устройств linux. Обратите внимание на самый первый символ в каждой строке. Он указывает тип устройства. Символом «b» — обозначаются блочные устройства linux (block), а символом «c» — символьные (character).
Более точно можно идентифицировать устройства по их младшему и старшему номеру. Например, жесткие диски имеют старший номер 8, что обозначает их как блочные устройства SCSI. Обратите внимание, что все жесткие диски PATA и SATA находятся под управлением SCSI. Раньше использовалась подсистема ATA, но она уже устарела, поэтому диски, которые раньше обозначались как hd[a-z] теперь обозначаются sd[a-z].
Младший номер диска означает раздел устройства, например, номера 8/0 — это весь диск /dev/sda, а 8/1 уже файл первого раздела на диске, 8/6 — /dev/sda6. Файлы TTY именуются немного по-другому, от tty0 до tty63. Все значения старших номеров устройств Linux вы можете найти на официальном сайте ядра.
Работа с устройствами в Linux
Давайте проведем несколько экспериментов, которые помогут вам понять как работают устройства Linux и как ими управлять в этой операционной системе. Большинство дистрибутивов Linux имеют несколько виртуальных консолей, обычно от 1 до 7, которые могут использоваться для входа в сеанс командной оболочки. К этим виртуальным консолям можно получить доступ с помощью сочетаний клавиш Ctrl+Alt+Fn, например, Ctrl+Alt+F1 для первой консоли, Ctrl+Alt+F2 для второй и так далее.
Сейчас нажмите Ctrl+Alt+F2 для перехода во вторую консоль, в некоторых дистрибутивах, кроме запроса логина и пароля, будет выведена информация про активную TTY связанную с этой консолью. Но этой информации может и не быть. В данном случае консоль будет связана с устройством tty2.
Войдите от имени обычного пользователя, затем наберите такую команду, чтобы посмотреть номер устройства tty:
У меня вы видите устройство /dev/pts/0, это виртуальное устройство эмулятора терминала, но если вы будете выполнять задачу в tty2, то отобразиться именно она. Теперь давайте посмотрим список tty устройств с помощью команды ls:
Нас будут интересовать не все устройства, а только первые три. В этих устройствах нет ничего особенного, это обычные устройства символьного типа. Устройство tty2 подключено к консоли 2, устройство tty3 подключено к консоли 3.
Нажмите сочетание клавиш Ctrl+Alt+F3, чтобы переключиться в третью консоль, затем выполните команду:
echo «Hello world» > /dev/tty2
Затем вернитесь во вторую консоль. Здесь вы увидите отправленную строку, Hello World. Все это можно повторить с помощью эмуляторов терминала в графическом интерфейсе, только здесь будут использоваться псевдо-терминальные устройства /dev/pts/*. Теперь попробуем отобразить содержимое файла fstab с помощью cat в другом терминале:
cat /etc/fstab > /dev/tty2
С помощью cat вы можете отправить файл непосредственно на принтер. Например, если устройство принтера /dev/usb/lp0, то для печати файла будет достаточно выполнить:
cat test.pdf > /dev/usb/lp0
Каталог /dev/ содержит много интересных файлов устройств. Это интерфейсы доступа к аппаратному обеспечению и вам не нужно думать, что это, жесткий диск или экран. Например, вся оперативная память компьютера доступна в виде устройства /dev/mem. С помощью него вы можете иметь прямой доступ к памяти. Мы можем вывести содержимое памяти в терминал:
dd if=/dev/mem bs=2048 count=100
Утилита dd, в отличие от cat дает больше контроля над процессом и позволяет указать сколько данных нужно прочитать. Но не ко всей памяти вы можете получить доступ. В ядре встроена защита, поэтому обычно, вы можете читать память, только для своего процесса.
Также тут есть файлы, которые несвязанны ни с какими реальными устройствами, это null, zero, random и urandom. Устройство /dev/null может использоваться для перенаправления вывода команд, чтобы данные никуда не выводились. Устройство /dev/zero используется для получения строки, заполненной нулями.
Вы можете использовать ту же команду dd, чтобы попытаться вывести ряд символов с устройства /dev/null:
dd if=/dev/null bs=512 count=500 | od -c
Обратите внимание, что ничего выведено не будет, потому что это устройство пусто, оно только принимает данные и никуда их не сохраняет.
Устройства /dev/random и /dev/urandom позволяют получить случайные комбинации чисел или байт. Вы можете использовать такую команду, чтобы получить случайные байты информации:
Для остановки нажмите Ctrl+C. Устройство urandom позволяет генерировать случайные последовательности независимые от предыдущего числа, в качестве источника энтропии используется нажатия клавиш и движения мыши.
Устройство /dev/zero позволяет получить строку, заполненную нулями. Для проверки используйте такую команду:
dd if=/dev/zero bs=512 count=500 | od -c
Обратите внимание, что восьмеричные нули и нули ASCII это не одно и то же.
Создание устройств в Linux
В прошлом все устройства из каталога /dev создавались во время установки системы, а это означало, что каталог содержал все возможные поддерживаемые устройства, даже если они не использовались. Если вам нужно было создавать или переинициализировать файлы устройств, использовалась утилита mknod. Но для работы с ней вам нужно знать старший и младший номер устройства.
Сейчас ситуация изменилась и все файлы устройств linux создаются во время загрузки только для нужных устройств. Менеджер устройств следит за подключаемыми и отключаемыми устройствами и добавляет или удаляет соответствующие файлы. Вы можете убедиться, что устройства были созданы сейчас просмотрев дату создания в с помощью команды ls.
Команда mknod все еще есть, но уже существует более новая разработка — makedev. Она предоставляет очень простой интерфейс для создания устройств.
Выводы
В этой статье мы рассмотрели подключенные устройства linux, а также как выполняется работа с устройствами в Linux. Конечно, в одной статье невозможно полностью охватить такую огромную тему, но я надеюсь что у вас появились некоторые базовые навыки работы использования файлов устройств и эта статья была вам полезной.
Источник