В Linux есть специальные файлы, которые на самом деле не являются файлами.
Наиболее заметные и наглядные примеры из них находятся в dev
папке «файлы», например:
/dev/null
- игнорирует все, что вы пишете в файл/dev/random
- выводит случайные данные вместо содержимого файла/dev/tcp
- Отправляет любые данные, которые вы пишете в этот файл по сети
Прежде всего, как называются эти типы «файлов», которые на самом деле являются замаскированным скриптом или двоичным файлом?
Во-вторых, как они созданы? Эти файлы встроены в систему на уровне ядра, или есть способ создать «волшебный файл» самостоятельно (как насчет a /dev/rickroll
)?
man 2 mknod
open()
,read()
,close()
и т.д. После этого, это до программного обеспеченияОтветы:
/dev/zero
является примером «специального файла» - в частности, «узла устройства». Обычно они получают созданные в процессе установки дистрибутива, но вы можете полностью создать их самостоятельно , если вы хотите.Если вы спросите
ls
о/dev/zero
:«C» в начале говорит вам, что это «символьное устройство»; другой тип - «блочное устройство» (печатается
ls
как «b»). Грубо говоря, устройства с произвольным доступом, такие как жесткие диски, как правило, являются блочными устройствами, в то время как последовательные устройства, такие как ленточные накопители или ваша звуковая карта, обычно являются символьными устройствами.Часть «1, 5» - это «основной номер устройства» и «вспомогательный номер устройства».
Имея эту информацию, мы можем использовать
mknod
команду для создания нашего собственного узла устройства:Это создает новый файл с именем
foobar
, в текущей папке, которая делает точно то же самое , как/dev/zero
. (Конечно, вы можете установить для него различные разрешения, если хотите.) Все, что действительно содержит этот «файл», это три элемента выше - тип устройства, основной номер, вспомогательный номер. Вы можете использоватьls
для поиска кодов для других устройств и воссоздать их тоже. Когда вам надоест, просто используйте,rm
чтобы удалить узлы устройства, которые вы только что создали.В основном, старший номер сообщает ядру Linux, с каким драйвером устройства следует обращаться, а младший номер указывает драйверу устройства, о каком устройстве вы говорите. (Например, у вас, вероятно, один контроллер SATA, но, возможно, к нему подключено несколько жестких дисков.)
Если вы хотите изобретать новые устройства, которые делают что-то новое ... ну, вам нужно отредактировать исходный код для ядра Linux и скомпилировать собственное ядро. Так что давайте не будем этого делать! :-) Но вы можете добавить файлы устройств, которые дублируют те, которые вы уже получили, просто отлично. Автоматизированная система , как Udev в основном просто наблюдая за событиями устройства и вызова
mknod
/rm
автоматически. Ничего более волшебного, чем это.Есть еще другие виды специальных файлов:
Linux считает каталог специальным видом файла. (Обычно вы не можете напрямую открыть каталог, но если бы вы могли, вы обнаружите, что это обычный файл, который содержит данные в специальном формате и сообщает ядру, где найти все файлы в этом каталоге.)
Симлинк это специальный файл. (Но жесткой ссылки нет.) Вы можете создавать символические ссылки с помощью
ln -s
команды. (Поищите справочную страницу для этого.)Есть также вещь, называемая «именованный канал» или «FIFO» (очередь «первым пришел - первым вышел»). Вы можете создать один с
mkfifo
. FIFO - это магический файл, который может быть открыт сразу двумя программами - одно чтение, одно письмо. Когда это происходит, это работает как обычная оболочка. Но вы можете запустить каждую программу отдельно ...Файл, который не является «специальным» в любом случае, называется «обычным файлом». Вы иногда увидите упоминание об этом в документации Unix. Вот что это значит; файл, который не является узлом устройства, символической ссылкой или чем-то еще. Просто обычный, каждый день файл без магических свойств.
источник
mknod
, бегите,cat /proc/devices
чтобы увидеть основные цифры для всех водителей. Что приводит нас к еще одному виду специальных файловых/proc
файловых систем ( этот ответ говорит об этом).Большинство
/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
Разница
ksh93
в томbash
, что TCP-соединения будут выполняться только с операторами перенаправления, а не в других местах, где он может открывать файлы, такие как встроеннаяsource
или.
.источник
gawk
аналогично особым случаям/inet{,4,6}/{tcp,udp}/$port/$remote/$rport
, начиная примерно с 2010 года (я точно не помню и не могу найти заметки о выпуске)./dev/tcp
том, что это НЕ файл. Там никогда не будет файла с именем этого. Синтаксис Bash для открытия сокетов использует строку/dev/tcp/address
как имя файла, но называть ее «файл, реализованный в пространстве пользователя», звучит странно. Интересно, чтоksh
эти имена перехватывают все, а не только перенаправления. Это ближе к "реализации файла".bash
только скопировал это поведение, но оно происходит в другом месте.Помимо узлов устройств, описанных в других ответах (созданных с помощью mknod (2) или предоставленных некоторыми devfs ), в Linux есть и другие «магические» файлы, предоставляемые специальными виртуальными файловыми системами , в частности, в
/proc/
(см. Proc (5) , читайте о procfs). ) и в/sys/
(читайте о sysfs ).Эти псевдофайлы (которые появляются от -eg до stat (2) - как обычные файлы, а не как устройства) - это виртуальное представление, предоставляемое ядром; в частности, чтение с
/proc/
(например, с помощьюcat /proc/$$/maps
или с помощью open (2) -ing/proc/self/status
в вашей программе), как правило, не требует физического ввода-вывода с диска или сети, поэтому выполняется довольно быстро.Чтобы создать какой-то дополнительный псевдофайл,
/proc/
вам, как правило, следует написать собственный модуль ядра и загрузить его (см., Например, это ).источник
Они называются узлами устройства и создаются вручную
mknod
или автоматическиudev
. Обычно это файловые интерфейсы для символьных или блочных устройств с драйверами в ядре - например, диски - это блочные устройства, ttys и последовательные порты и т. Д. - символьные устройства.Существуют и другие «специальные» типы файлов, в том числе именованные каналы, fifo и сокеты.
источник
Как другие пользователи уже объяснили очень подробно, специальные файлы требуют кода для их резервного копирования. Однако, похоже, никто не упомянул, что Linux предоставляет несколько способов написания этого кода в пространстве пользователя:
A. FUSE (Файловая система в USErspace) позволяет вам писать что-то вроде
/proc
без риска сбоя ядра и делать это на языке / среде выполнения по вашему выбору, таких как Go , Node.js , Perl , PHP , Python , Ruby , Rust , и т . д.Он также имеет преимущество в том, что файловые системы FUSE можно монтировать без,
sudo
потому что они работают как пользователь, выполняющий монтирование.Вот несколько примеров того, что люди написали с помощью FUSE:
Б. Если вы хотите создать виртуальное устройство ввода, такое как клавиатура, мышь, джойстик и т. Д. (Например, для написания драйвера пользовательского пространства для USB-устройства, с которым вы разговариваете
libusb
), есть вход .Связи для него найти сложнее, но я знаю, что они существуют для Go (только для клавиатуры), Python и Ruby (2) .
Примеры реального использования uinput включают в себя:
C. Для общих символьных устройств есть CUSE (Символьные устройства в USErspace). Это гораздо менее популярно, хотя.
Единственный пользователь CuSe API , что я лично в курсе, та же программа , что побудило его создание: osspd , который реализует
/dev/dsp
,/dev/adsp
и/dev/mixer
(аудио API OSS) в пользовательском пространстве , таким образом они могут быть проложены через PulseAudio или DMIX.Единственная привязка CUSE , которую мне удалось найти, это cusepy , которая не обновлялась с 2010 года.
D. Вам может вообще не понадобиться новый специальный файл.
Например, вы можете открыть необработанную связь с любым USB-устройством, используя libusb (Список привязок на странице), а затем обмениваться данными с другими программами через какой-то другой механизм (сокеты TCP / UDP, чтение / запись stdin / stdout или обычные файлы на диске). , и т.д.).
источник
poll
, но поскольку cusepy использует ctypes, а привязки генерируются автоматически на основе заголовочных файлов C, исправление любых отсутствующих функций - это просто добавление нужного имени функции в список экспортируемых функций вsetup.py
.В книге « Драйверы устройств Linux» (настоятельно рекомендуется) это подробно объясняется, и даже вам нужно создать модуль ядра, который делает это в качестве примера, но в двух словах, каждый драйвер устройства имеет определенные функции, которые вызываются при открытии, закрытии файла. , читать, писать и т. д. «Специальные» файлы просто делают что-то особенное внутри этих функций, а не обращаются к оборудованию хранения на диске.
Например, функция write для
/dev/null
just ничего не делает, игнорируя байты. Функция чтения для/dev/random
возвращает случайное число.источник
mount -t devtmpfs
Также интересно видеть, что в современных системах
/dev
обычно есть тип файловой системы, который может быть смонтирован где угодно. Ubuntu 16.04:Это включено
CONFIG_DEVTMPFS=y
и позволяет самому ядру создавать и уничтожать файлы устройств по мере необходимости.CONFIG_DEVTMPFS_MOUNT=y
Эта опция включает автоматическое монтирование ядра devtmpfs
/dev
.drivers/base/Kconfig
документы:file_operations
Наконец, вы должны создать свой собственный модуль ядра символьного устройства, чтобы точно увидеть, что происходит.
Вот минимальный исполняемый пример: Понимание файлов символьных устройств (или специальных символов)
Самый важный шаг, это настройка
file_operations
структуры, например:который содержит указатели на функции, которые вызываются для каждого системного вызова, связанного с файлом.
Тогда становится очевидным, что вы переопределяете эти системные вызовы, связанные с файлами, чтобы делать все, что хотите, и поэтому ядро реализует такие устройства, как
/dev/zero
.Создать
/dev
записи в автоматически безmknod
Последняя загадка - как ядро автоматически создает
/dev
записи.Механизм можно наблюдать, создав модуль ядра, который делает это самостоятельно, как показано по адресу: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- code-of-a-linux-kernel-module / 45531867 # 45531867 и сводится к
device_create
вызову.источник