В Unix-подобных операционных системах файл устройства или специальный файл — это интерфейс для драйвера устройства , который появляется в файловой системе так, как если бы это был обычный файл . Существуют также специальные файлы в DOS , OS/2 и Windows . Эти специальные файлы позволяют прикладной программе взаимодействовать с устройством, используя его драйвер устройства посредством стандартных системных вызовов ввода-вывода . Использование стандартных системных вызовов упрощает многие задачи программирования и приводит к согласованным механизмам ввода-вывода в пользовательском пространстве независимо от особенностей и функций устройства.
Файлы устройств обычно предоставляют простые интерфейсы для стандартных устройств (таких как принтеры и последовательные порты), но также могут использоваться для доступа к конкретным уникальным ресурсам на этих устройствах, например к разделам диска . Кроме того, файлы устройств полезны для доступа к системным ресурсам , которые не имеют связи с каким-либо реальным устройством, таким как приемники данных и генераторы случайных чисел .
В Unix-подобных операционных системах существует два основных типа файлов устройств: специальные символьные файлы и специальные блочные файлы . Разница между ними заключается в том, какой объем данных считывается и записывается операционной системой и оборудованием. Их вместе можно назвать специальными файлами устройства в отличие от именованных каналов , которые не связаны с устройством, но также не являются обычными файлами.
MS-DOS позаимствовала концепцию специальных файлов из Unix, но переименовала их в устройства . [1] Поскольку ранние версии MS-DOS не поддерживали иерархию каталогов , устройства отличались от обычных файлов наличием в их именах зарезервированных слов , например: infamous CON
. Они были выбраны из соображений совместимости с CP/M и до сих пор присутствуют в современной Windows для обеспечения обратной совместимости.
В некоторых Unix-подобных системах большинство файлов устройств управляются как часть виртуальной файловой системы, традиционно монтируемой по адресу /dev
, возможно, связанной с управляющим демоном, который отслеживает добавление и удаление оборудования во время выполнения, внося соответствующие изменения в файловую систему устройства, если это необходимо. не выполняется автоматически ядром и, возможно, вызывает сценарии в системе или пользовательском пространстве для удовлетворения особых потребностей устройства. FreeBSD , DragonFly BSD и Darwin имеют специальную файловую систему devfs ; Узлы устройств автоматически управляются этой файловой системой в пространстве ядра . Раньше в Linux была аналогичная реализация devfs , но позже от нее отказались, а затем удалили, начиная с версии 2.6.17; [2] Сейчас Linux в основном использует реализацию пользовательского пространства , известную как udev , но существует множество вариантов.
В системах Unix, которые поддерживают изоляцию процессов chroot , таких как контейнеры Solaris , обычно для каждой среды chroot требуется своя собственная среда /dev
; эти точки монтирования будут видны в операционной системе хоста в различных узлах дерева глобальной файловой системы. Ограничивая количество узлов устройств, заполняемых экземплярами chroot /dev
, аппаратная изоляция может быть обеспечена средой chroot (программа не может вмешиваться в оборудование, которое она не может ни видеть, ни называть — еще более сильная форма контроля доступа , чем разрешения файловой системы Unix ).
MS-DOS управляла конфликтами аппаратных устройств (см. программу резидентного завершения и пребывания ), открывая каждый файл устройства эксклюзивно. Приложение, пытающееся получить доступ к уже используемому устройству, обнаружит, что не может открыть узел файла устройства. В Unix и Linux реализована разнообразная семантика драйверов устройств , касающаяся одновременного доступа . [3]
Узлы устройств соответствуют ресурсам, которые ядро операционной системы уже выделило. Unix идентифицирует эти ресурсы по старшему и младшему номеру , [4] оба из которых хранятся как часть структуры узла . Присвоение этих номеров происходит однозначно в разных операционных системах и на разных компьютерных платформах . Как правило, старший номер идентифицирует драйвер устройства, а младший номер идентифицирует конкретное устройство (возможно, из многих), которым управляет драйвер: [5] в этом случае система может передать младший номер драйверу. Однако при наличии динамического распределения номеров это может быть не так (например, во FreeBSD 5 и выше).
Как и в случае с другими специальными типами файлов, компьютерная система обращается к узлам устройств с помощью стандартных системных вызовов и обрабатывает их как обычные компьютерные файлы. Существует два стандартных типа файлов устройств; к сожалению, их имена довольно нелогичны по историческим причинам, и в результате объяснения разницы между ними часто неверны.
Специальные символьные файлы или символьные устройства обеспечивают небуферизованный прямой доступ к аппаратному устройству. Они не обязательно позволяют программам читать или записывать отдельные символы за раз; это зависит от рассматриваемого устройства. Например, символьное устройство для жесткого диска обычно требует, чтобы все операции чтения и записи были выровнены по границам блоков, и наверняка не позволяет читать ни одного байта.
Символьные устройства иногда называют необработанными устройствами , чтобы избежать путаницы, связанной с тем фактом, что символьное устройство для части блочного оборудования обычно требует, чтобы программы читали и записывали выровненные блоки.
Блокировка специальных файлов или блочных устройств обеспечивает буферизованный доступ к аппаратным устройствам и некоторую абстракцию от их особенностей. [6] В отличие от символьных устройств, блочные устройства всегда позволяют программисту читать или записывать блок любого размера (включая отдельные символы/байты) и любого выравнивания. Обратной стороной является то, что, поскольку блочные устройства буферизуются, программист не знает, сколько времени пройдет, прежде чем записанные данные будут переданы из буферов ядра на фактическое устройство, или в каком порядке две отдельные записи поступят на физическое устройство. Кроме того, если одно и то же оборудование предоставляет как символьные, так и блочные устройства, существует риск повреждения данных из-за того, что клиенты, использующие символьное устройство, не знают об изменениях, внесенных в буферы блочного устройства.
Большинство систем создают как блочные, так и символьные устройства для представления оборудования, такого как жесткие диски. В частности, FreeBSD и Linux этого не делают; в первом удалена поддержка блочных устройств, [7] а во втором создаются только блочные устройства. В Linux, чтобы получить символьное устройство для диска, необходимо использовать «необработанный» драйвер, хотя можно получить тот же эффект, что и при открытии символьного устройства, открыв блочное устройство с помощью специфичного для Linux флага O_DIRECT .
Узлы устройств в Unix-подобных системах не обязательно должны соответствовать физическим устройствам . Узлы, у которых отсутствует это соответствие, образуют группу псевдоустройств . Они предоставляют различные функции, выполняемые операционной системой. Некоторые из наиболее часто используемых (символьных) псевдоустройств включают в себя:
Кроме того, псевдоустройства, специфичные для BSD, с интерфейсом ioctl также могут включать в себя:
Узлы создаются системным вызовом mknod . Программа командной строки для создания узлов также называется mknod . Узлы можно перемещать или удалять с помощью обычных системных вызовов файловой системы ( rename , unlink ) и команд ( mv , rm ).
Некоторые версии Unix включают сценарий makedev или MAKEDEV для создания всех необходимых устройств в каталоге /dev . Это имеет смысл только в системах, устройствам которых статически присвоены старшие номера (например, посредством жесткого кодирования их в модуле ядра).
В то время как некоторые другие системы Unix, такие как FreeBSD , использовали управление узлами устройств на основе ядра только через devfs и не поддерживали создание узлов вручную. Системный вызов mknod(2) и команда mknod(8) существуют для обеспечения совместимости с POSIX, но созданные вручную узлы устройств вне devfs вообще не будут работать. [9]
Следующие префиксы используются в именах некоторых устройств в иерархии /dev для идентификации типа устройства:
Некоторые дополнительные префиксы стали широко использоваться в некоторых операционных системах:
Канонический список префиксов, используемых в Linux, можно найти в списке устройств Linux , официальном реестре выделенных номеров устройств и узлов каталога /dev для операционной системы Linux. [10]
Для большинства устройств за этим префиксом следует номер, однозначно идентифицирующий конкретное устройство. Для жестких дисков буква используется для идентификации устройств, а за ней следует номер для обозначения разделов . Таким образом, файловая система может, например, «знать» область на диске как /dev/sda3 или «видеть» сеанс сетевого терминала, связанный с /dev/pts/14 .
На дисках, использующих типичную главную загрузочную запись ПК, номера устройств основного и дополнительного расширенного раздела пронумерованы от 1 до 4, а индексы любых логических разделов — от 5 и выше, независимо от структуры предыдущих разделов (их родительских расширенных разделов). раздел не обязательно должен быть четвертым разделом на диске, и не обязательно должны существовать все четыре основных раздела).
Имена устройств обычно не переносятся между различными вариантами Unix-подобных систем, например, в некоторых системах BSD устройства IDE называются /dev/wd0 , /dev/wd1 и т. д.
devfs — это конкретная реализация файловой системы устройства в Unix-подобных операционных системах, используемая для представления файлов устройства. Базовый механизм реализации может различаться в зависимости от ОС.
Хранить эти специальные файлы в физически реализованной файловой системе, такой как жесткий диск, неудобно, и, поскольку для этого в любом случае требуется помощь ядра, возникла идея специальной логической файловой системы, которая не хранится физически.
Определить, когда устройства готовы появиться, непросто. Подход devfs заключается в том, что драйвер устройства запрашивает создание и удаление записей devfs, связанных с устройствами, которые он включает и отключает.
Файл устройства — это зарезервированное ключевое слово, используемое в системах PC DOS , TOS , OS/2 и Windows для разрешения доступа к определенным портам и устройствам.
MS-DOS позаимствовала концепцию специальных файлов из Unix, но переименовала их в устройства . [1] Поскольку ранние версии MS-DOS не поддерживали иерархию каталогов , устройства отличались от обычных файлов тем, что их имена составляли зарезервированные слова . Это означает, что определенные имена файлов были зарезервированы для устройств и не должны использоваться для именования новых файлов или каталогов. [11]
Сами зарезервированные имена были выбраны для совместимости с обработкой PIP
команд в «специальных файлах» в CP/M . В DOS существовало два типа устройств: блочные устройства (используемые для дисковых накопителей) и символьные устройства (как правило, все остальные устройства, включая устройства COM и PRN). [12]
DOS использует файлы устройств для доступа к принтерам и портам. Большинство версий Windows также содержат такую поддержку, что может вызвать путаницу при попытке создать файлам и папкам определенные имена, поскольку они не могут иметь эти имена. [13] Версии 2.x MS-DOS содержат параметр AVAILDEV
CONFIG.SYS , который, если он установлен в значение FALSE
, делает эти специальные имена активными только с префиксом \DEV\
, что позволяет создавать обычные файлы с этими именами. [14]
GEMDOS , DOS-подобная часть Atari TOS , поддерживала имена устройств, аналогичные DOS, но в отличие от DOS требовала завершающего символа ":" (в DOS это необязательно), чтобы идентифицировать их как устройства, а не обычные имена файлов (таким образом, " CON:» будет работать как в DOS, так и в TOS, но «CON» будет называть обычный файл в TOS, а консольное устройство — в DOS). В MiNT и MagiC специальное UNIX-подобное представление единой файловой системы, доступ к которому осуществляется через букву диска «U:», также помещает файлы устройств в «U:\DEV».
Используя перенаправление оболочки и каналы, данные можно отправлять на устройство или получать с него. Например, если ввести следующую команду, файл будет отправлен c:\data.txt
на принтер:
ТИП c:\data.txt > PRN
PIPE, MAILSLOT и MUP — это другие стандартные устройства Windows. [20]
8-битная операционная система карманных компьютеров Sharp , таких как PC-E500 , PC-E500S и т. д., состоит из интерпретатора BASIC , системы управления файлами (FCS), подобной DOS 2, реализующей элементарную 12-битную файловую систему, подобную FAT , и BIOS-подобная система управления вводом/выводом (IOCS), реализующая ряд стандартных драйверов символьных и блочных устройств, а также специальные файловые устройства, включая STDO:/SCRN: (дисплей), STDI:/KYBD: (клавиатура), COM: ( последовательный ввод/вывод), STDL:/PRN: (принтер), CAS: (кассета), E:/F:/G: (файл памяти), S1:/S2:/S3: (карта памяти), X: /Y: (дискета), SYSTM: (система) и NIL: (функция). [21]
Следующим шагом после открытия одного устройства является разрешение одному пользователю открывать устройство в нескольких процессах, но разрешить одновременное открытие устройства только одному пользователю.
Devfsd обеспечивает настраиваемое управление узлами устройств с использованием файловой системы устройств Linux.