
В Linux есть специальные файлы, которые на самом деле не являются файлами.
Наиболее заметные и наглядные примеры этого находятся в dev
папке «файлы», например:
/dev/null
- Игнорирует все, что вы записываете в файл/dev/random
- Выводит случайные данные вместо содержимого файла/dev/tcp
- Отправляет любые данные, которые вы записываете в этот файл, по сети.
Прежде всего, как называются эти типы «файлов», которые на самом деле представляют собой некий вид замаскированного скрипта или двоичного файла?
Во-вторых, как они создаются? Встроены ли эти файлы в систему на уровне ядра или есть способ создать "волшебный файл" самостоятельно (как насчет /dev/rickroll
)?
решение1
/dev/zero
является примером "специального файла" — в частности, "узла устройства". Обычно они создаются в процессе установки дистрибутива, но вы можетеполностьюЕсли хотите, создайте их сами.
Если вы спрашиваете ls
о /dev/zero
:
# ls -l /dev/zero
crw-rw-rw- 1 root root 1, 5 Nov 5 09:34 /dev/zero
«c» в начале говорит вам, что это «символьное устройство»; другой тип — «блочное устройство» (печатается как ls
«b»). Грубо говоря, устройства с произвольным доступом, такие как жесткие диски, как правило, являются блочными устройствами, в то время как последовательные устройства, такие как ленточные накопители или ваша звуковая карта, как правило, являются символьными устройствами.
Часть «1, 5» — это «основной номер устройства» и «вспомогательный номер устройства».
Имея эту информацию, мы можем использовать mknod
команду для создания нашего собственного узла устройства:
# mknod foobar c 1 5
Это создает новый файл с именем foobar
в текущей папке, который делаетточното же самое, что и /dev/zero
. (Конечно, вы можете установить другие разрешения на него, если хотите.) Все, что этот «файл» на самом деле содержит, это три элемента выше — тип устройства, основной номер, дополнительный номер. Вы можете использовать ls
для поиска кодов для других устройств и воссоздания их тоже. Когда вам надоест, просто используйте rm
для удаления узлов устройств, которые вы только что создали.
По сути, старший номер сообщает ядру Linux, с каким драйвером устройства следует взаимодействовать, а младший номер сообщает драйверу устройства, о каком устройстве идет речь. (Например, у вас, вероятно, один контроллер SATA, но к нему может быть подключено несколько жестких дисков.)
Если вы хотитеизобретатьновые устройства, которые делают что-то новое... ну, вам нужно будет редактировать исходный код ядра Linux и компилировать свое собственное ядро. Так что давайте не будем этого делать! :-) Но вы можете добавлять файлы устройств, которые дублируют те, которые у вас уже есть, и это прекрасно. Автоматизированная система, такая как udev, в основном просто следит за событиями устройств и автоматически вызывает mknod
/ rm
для вас. Ничего более магического, чем это.
Есть ещедругойвиды специальных файлов:
Linux рассматривает каталог как особый вид файла. (Обычно вы не можете напрямую открыть каталог, но если бы вы могли, вы бы обнаружили, что это обычный файл, содержащий данные в специальном формате и сообщающий ядру, где найти все файлы в этом каталоге.)
Символическая ссылка — это специальный файл. (Но жесткая ссылка таковой не является.) Вы можете создавать символические ссылки с помощью
ln -s
команды. (Поищите ее в man-странице.)Есть также вещь, называемая "именованный канал" или "FIFO" (очередь "первым пришел, первым вышел"). Вы можете создать его с помощью
mkfifo
. FIFO - это волшебный файл, который можно открыть с помощьюдвапрограммы одновременно — одно чтение, одно написание. Когда это происходит, это работает как обычный конвейер оболочки. Но вы можете запустить каждую программу отдельно...
Файл, который не является "специальным" ни в каком смысле, называется "обычным файлом". Вы иногда будете видеть упоминание об этом в документации Unix. Вот что это значит: файл, который не является узлом устройства или символической ссылкой или чем-то еще. Просто обычный, повседневный файл без каких-либо магических свойств.
решение2
Большинство записей /dev
представляют собой иноды блочных устройств или иноды символьных устройств.В Википедии много подробностейоб этом я не буду повторяться.
Но /dev/tcp
то, что упомянуто в вашем вопросе, не объясняется ни одним из существующих ответов. /dev/tcp
и /dev/udp
отличается от большинства других /dev
записей. Блочные и символьные устройства реализованы ядром, но /dev/tcp
и /dev/udp
реализованы в пользовательском режиме.
Оболочка bash — это одна из программ, которая имеет реализацию /dev/tcp
и /dev/udp
(скопирована из ksh93
). Когда вы пытаетесь открыть путь ниже тех, которые содержат операторы перенаправления bash, она не выполнит обычный open
системный вызов. Вместо этого bash создаст сокет TCP и подключит его к указанному порту.
Это реализовано в пользовательском режиме и только в некоторых программах, как можно увидеть в следующем примере, который демонстрирует разницу между разрешением bash
и cat
попыткой открытия./dev/tcp/::1/22
$ cat /dev/tcp/::1/22
cat: /dev/tcp/::1/22: No such file or directory
$ cat < /dev/tcp/::1/22
SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.3
Разница в ksh93
том, что он bash
будет выполнять только TCP-соединения с операторами перенаправления, а не в других местах, где он может открывать файлы, например, source
или .
встроенный.
решение3
В дополнение к узлам устройств, описанным в других ответах (созданных с помощьюmknod(2)или поставляемый некоторымиdevfs), Linux имеет другие "волшебные" файлы, предоставляемые специальнымивиртуальные файловые системы, в частности /proc/
(см.процесс(5), прочитать оprocfs) и в /sys/
(читайте оsysfs).
Эти псевдофайлы (которые появляются, например,стат(2)- как обычные файлы, а не как устройства) представляют собой виртуальное представление, предоставляемое ядром; в частности, чтение из /proc/
(например cat /proc/$$/maps
, с помощью или с помощьюоткрыть(2)-в /proc/self/status
вашей программе) обычно не требует физического ввода-вывода с диска или из сети, поэтому выполняется довольно быстро.
Чтобы создать какой-то дополнительный псевдофайл, /proc/
вам обычно приходится писать свой собственныймодуль ядраи загрузите его (см. напримерэтот).
решение4
Как уже подробно объяснили другие пользователи, специальные файлы требуют кода для их резервного копирования. Однако никто, похоже, не упомянул, что Linux предоставляет несколько способов написать этот код в пользовательском пространстве:
А. ПРЕДОХРАНИТЕЛЬ(Файловая система в пользовательском пространстве) позволяет вам писать что-то вроде /proc
без риска сбоя ядра и делать это на языке/в среде выполнения по вашему выбору, напримерИдти,Node.js,Перл,PHP,Питон, Рубин,Ржавчина,и т. д..
Преимущество также в том, что файловые системы FUSE можно монтировать без них, sudo
поскольку они запускаются от имени пользователя, выполняющего монтирование.
Вот несколько примеров того, что люди написали с помощью FUSE:
- mp3fs(Просматривайте файлы FLAC как файлы MP3, которые создаются «на лету» при копировании/перетаскивании их на MP3-плеер)
- PyTagsFS(Просматривайте свои медиафайлы в дереве виртуальных папок, созданном на основе тегов метаданных)
- предохранитель-молния(Монтировать Zip-файлы как папки)
- FuseISO(Монтировать ISO-образы без прав root)
- iFUSE(Монтировать iDevices)
- FuseDAV(Монтировать общие ресурсы WebDAV)
- предохранитель-exfat(Монтирование файловых систем в формате exFAT)
- ntfs-3g(TheДрайвер Linux NTFS)
Б.Если вы хотите создать виртуальное устройство ввода, такое как клавиатура, мышь, джойстик и т. д. (например, чтобы написать драйвер пользовательского пространства для USB-устройства, с которым вы общаетесь с помощью libusb
), естьuinput.
Крепления для него найти сложнее, но я знаю, что они существуют.Идти(Только клавиатура),Питон, иРубин (2).
Примеры реального использования uinput включают в себя:
- G15Daemon(Драйвер Linux для ЖК-дисплея и игровых клавиш на игровых клавиатурах Logitech G15)
- ds4drv(Драйвер для контроллеров Sony DualShock 4)
- xboxdrv(Альтернативный драйвер контроллера XBox 360 и эквивалент для Linuxx360ceнастолько плохо спроектированные игры, какRunner2: Будущая легенда ритма Alienмогут думать, что они общаются с настоящим контроллером XBox, хотя это не так)
- Старые драйверы Wiimote, такие какcwiidкоторые были необходимы до того, как кто-то наконец написал драйвер ядра Wiimote, чтобы поддержка была доступна по умолчанию.
С.Для универсальных символьных устройств естьКьюз(Символьные устройства в USErspace). Хотя он гораздо менее популярен.
Единственный пользователь API CUSE, о котором я лично знаю, — это та же программа, которая и побудила его создать:осспд, который реализует /dev/dsp
, /dev/adsp
, и /dev/mixer
(аудио API OSS) в пользовательском пространстве, чтобы их можно было направлять через PulseAudio или dmix.
Единственное связывание CUSE, которое мне удалось найти, этокузепи, который не обновлялся с 2010 года.
Д.Возможно, вам вообще не понадобится новый специальный файл.
Например, вы можете открыть прямое соединение с любым USB-устройством, используяlibusb(Список привязок на странице) и затем взаимодействовать с другими программами через какой-либо другой механизм (сокеты TCP/UDP, чтение/запись stdin/stdout или обычных файлов на диске и т. д.).