Як створюються «/ dev» файли Linux?


112

У Linux є спеціальні файли, які насправді не є файлами.

Найбільш помітні і зрозумілі приклади цього - у devпапці, "файли" на зразок:

  • /dev/null - Ігнорує все, що ви пишете у файл
  • /dev/random - Виводить випадкові дані замість вмісту файлу
  • /dev/tcp - Надсилає будь-які дані, які ви записуєте в цей файл по мережі

Перш за все, як називаються ці типи "файлів", які насправді є певним сценарієм чи бінарними масками?

По-друге, як вони створені? Ці файли вбудовані в систему на рівні ядра, чи є спосіб створити "чарівний файл" самостійно (як щодо /dev/rickroll)?


1
Я не мав поняття, як позначити це питання, тим більше, що я не знаю назви того, що шукаю. Не соромтеся редагувати будь-які відповідні теги.
IQAndreas

15
До речі, це фундаментальна частина дизайну unix та unix-подібних операційних систем: (майже) все є файлом, або його можна зробити так, щоб виглядати як файл.
cas

5
Також дивіться: mknod (2) man 2 mknod
RobertL

4
Це "вузли пристроїв". Однак ті, які ви згадали - на відміну від дисків, клавіатури, мишей, аудіокарт та інших пристроїв - це так звані "псевдопристрої", оскільки вони не є "справжніми" пристроями і існують лише в ядрі. Можна створити нові, записавши відповідний драйвер пристрою та додати його до ядра (наприклад, псевдопристрій для контролю деякої активності на комп'ютері). До існування каталогу / dev на диску - це віртуальна файлова система (типу devfs), створена ядром.
Баард Копперуд

10
Усі файли, навіть "справжні" файли, - це програмні артефакти. Програмне забезпечення за кожен пристрій, файл, сокет, спеціальний файл, або що - то ще не винайдено містить таблицю функцій для обробки open(), read(), close()і т.д. Після цього, це до програмного забезпечення
waltinator

Відповіді:


101

/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команди. (Знайдіть сторінку для цього.)

  • Існує також річ, яка називається "названа труба" або "FIFO" (черга першої входу, перша вихід). Ви можете створити його за допомогою mkfifo. FIFO - це чарівний файл, який можна відкрити відразу двома програмами - одним читанням, одним написанням. Коли це відбувається, він працює як звичайна оболонка. Але ви можете запустити кожну програму окремо ...

Файл, який ні в якому разі не є "спеціальним", називається "звичайним файлом". Ви час від часу бачите згадування про це в документації Unix. Ось що це означає; файл, який не є вузлом пристрою чи символьним посиланням чи будь-яким іншим. Просто нормальний щоденний файл без магічних властивостей.


4
Існує також ще один тип спеціального файлу, сокет домену Unix, прив’язаний до файлової системи.
Брайан Бі

8
Якщо ви хочете грати mknod, запустіть, cat /proc/devicesщоб побачити основні номери для всіх водіїв. Це приводить нас до ще одного виду спеціального файлової /procфайлової системи ( ця відповідь говорить про це).
угорен

8
Інші уніці винайшли свої спеціальні файли, наприклад, у Соляріса були двері .
Кевін

6
Незначна нітпік: вам не доведеться перекомпілювати ядро, щоб написати новий символ / блок пристрою :) crashcourse.ca/introduction-linux-kernel-programming/… Інакше це справді хороша відповідь, +1!
Командир Коріандр Саламандер

1
@MathematicalOrchid: крок у вашій відповіді відсутній (або, принаймні, лише неявно) - це той факт, що ці спеціальні файли взагалі не маскуються скриптами або бінарними файлами оболонки (як мається на увазі питання), а швидше інтерфейсом для доступу до функціональних можливостей, які є в наявності в ядрі ОС.
Сонник

34

Більшість /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або .вбудований.


Крім того, GNU пробуджує gawkподібні спеціальні випадки /inet{,4,6}/{tcp,udp}/$port/$remote/$rport, оскільки десь близько 2010 року (я не пригадую точно і не можу знайти нотатки до випуску).
dave_thompson_085

6
IMO, кращий спосіб заявити про /dev/tcpте, що це НЕ файл. Ніколи не існує файлу, який називається таким. Синтаксис Баша для відкриття сокетів використовує рядок, /dev/tcp/addressяк ім'я файлу, але називати його "файлом, реалізованим у просторі користувача", просто звучить дивно. Цікаво, що kshці файли підключаються до всього, а не лише до переадресації. Це ближче до "реалізації файлу".
Пітер Кордес

@PeterCordes Я вважаю, що UWIN встановлює їх як фактичні файли. і я думаю, що 3dfs робить те саме. пам’ятайте, bashлише скопіювали цю поведінку, але вона бере свій початок в іншому місці.
mikeserv

19

Крім вузлів пристроїв описано в інших відповідях (створених з MKNOD (2) або поставляються деякої DevFS ), Linux має інші «магічні» файли , що надаються спеціальні файлові системи віртуальних , зокрема , в /proc/(див процедурного (5) , читати про PROCFS ) та в /sys/(читайте про sysfs ).

Ці псевдофайли (які з'являються на зразок stat (2) - як звичайні файли, а не як пристрої) - це віртуальний вигляд, наданий ядром; зокрема, читання з /proc/(наприклад cat /proc/$$/maps, з відкритим (2) -ing /proc/self/statusу вашій програмі), як правило, не передбачає фізичного вводу / виводу з диска чи мережі, тому досить швидко.

Щоб створити якийсь додатковий псевдофайл, /proc/вам зазвичай слід написати власний модуль ядра та завантажити його (див., Наприклад, це ).


3
AFAIK застаріла інформація про продовження / закупівель. Хоча технічно це можливо, / proc (а точніше profs) повинен зберігати інформацію лише про запущені процеси. Усі інші псевдофайли, включаючи ті, що містять інформацію про час виконання або параметри конфігурації для ядра, повинні перейти в / sys (sysfs). Є ще псевдофайли, які не пов'язані з процесом, в / proc (наприклад, meminfo, cpuinfo) з міркувань сумісності, але нові псевдофайли повинні переходити в sysfs.
Сонник

13

Вони називаються вузлами пристроїв і створюються або вручну, mknodабо автоматично udev. Вони, як правило, схожі на файли інтерфейси для символьних або блокових пристроїв з драйверами ядра - наприклад, диски - це блокові пристрої, ttys і послідовні порти тощо - це символьні пристрої.

Існують і інші "спеціальні" типи файлів, включаючи названі труби, фіфоси та розетки.


9

Як уже пояснили інші користувачі дуже докладно, для створення резервних копій спеціальних файлів потрібен код. Однак, схоже, ніхто не згадував, що Linux надає кілька способів написання цього коду в просторі користувачів:

A. FUSE (Filesystem в USErspace) дозволяє написати щось на кшталт, /procне ризикуючи зірвати ядро, і зробити це мовою / режимом виконання на ваш вибір, наприклад, Go , Node.js , Perl , PHP , Python , Ruby , Rust , тощо .

Він також має перевагу в тому, що файлові системи FUSE можна монтувати без того, sudoщо вони працюють так, як користувач виконує монтаж.

Ось кілька прикладів того, що люди написали за допомогою програми FUSE:

  • mp3fs (Переглядайте файли FLAC як MP3-файли, які створюються під час льоту, коли ви копіюєте / перетягуєте їх на MP3-програвач)
  • PyTagsFS (Перегляд медіа у дереві віртуальних папок, побудованих із тегів метаданих)
  • fuse-zip (Mount Zip-файли як папки)
  • FuseISO (Монтувати ISO без кореневих дозволів)
  • iFUSE (Mount iDevices)
  • FuseDAV (акції Mount WebDAV)
  • fuse-exfat ( монтувати файлові системи у форматі exFAT)
  • NTFS-3g ( драйвер Linux NTFS)

B. Якщо ви хочете створити віртуальний пристрій введення даних, наприклад клавіатуру, мишу, джойстик тощо (наприклад, написати драйвер простору користувача для USB-пристрою, з яким ви розмовляєте libusb), немає вводу .

Прив’язки до нього важче знайти, але я знаю, що вони існують для Go (лише для клавіатури), Python та Ruby (2) .

Приклади використання реального входу в реальному світі включають:

  • G15Daemon (драйвер Linux для LCD та ігрових клавіш на ігрових клавіатурах Logitech G15)
  • ds4drv (драйвер для контролерів Sony DualShock 4)
  • xboxdrv (Альтернативний драйвер контролера XBox 360 та Linux, еквівалентний x360ce, такі погано розроблені ігри, як Runner2: Future Legend of Rhythm Alien, можуть подумати, що вони спілкуються зі справжнім контролером XBox, коли їх немає)
  • Старі драйвери Wiimote люблять cwiid, які потрібні, перш ніж хтось нарешті написав драйвер Wiimote ядра, щоб підтримка була доступна за замовчуванням.

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 або звичайні файли на диску тощо).


1
cusepy, можливо, не оновлювався деякий час (насправді він ніколи не оновлювався; він має лише один фіксатор!), але щойно записавши символьний пристрій за допомогою cusepy кілька тижнів тому, я можу підтвердити, що він все ще працює добре. У ньому бракувало декількох функцій, пов’язаних з реалізацією poll, але оскільки cusepy використовує ctypes, а прив'язки автоматично генеруються на основі файлів заголовків C, виправлення будь-яких відсутніх функцій - лише питання додавання потрібного імені функції до списку експортованих функцій у setup.py.
Алексі Торхамо

1
Ще один цікавий приклад використання FUSE - sshfs . Це дозволяє переглядати віддалену файлову систему так, ніби вона була локальною, використовуючи SSH-з'єднання під нею.
Містер Безсмертний

@ Mr.Deathless Так. Я фактично використовую це і мав на увазі згадати це, але забув.
ssokolow

6

Книга драйверів пристроїв Linux (настійно рекомендується) пояснює це докладно, і навіть ви створили модуль ядра, який робить це як приклад, але, у двох словах, кожен драйвер пристрою має конкретні функції, які викликаються, коли файл відкривається, закривається , читати, писати і т. д. "Спеціальні" файли просто роблять щось особливе всередині цих функцій, замість доступу до обладнання для зберігання даних на диску.

Наприклад, функція запису /dev/nullпросто нічого не робить, ігноруючи байти. Функція читання для /dev/randomповернення випадкового числа.


1

mount -t devtmpfs

Цікаво також побачити, що в сучасних системах, /devяк правило , є тип файлової системи, який можна встановити куди завгодно. Ubuntu 16.04:

mkdir d
sudo mount -t devtmpfs none d
head -c 10 d/random
sudo umount d

Це ввімкнено CONFIG_DEVTMPFS=yі дозволяє самому ядру створювати та знищувати файли пристроїв за потребою.

CONFIG_DEVTMPFS_MOUNT=y

Цей параметр робить ядро ​​автоматично встановленим devtmpfs /dev.

drivers/base/Kconfig документи:

config DEVTMPFS_MOUNT
    bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs"
    depends on DEVTMPFS
    help
      This will instruct the kernel to automatically mount the
      devtmpfs filesystem at /dev, directly after the kernel has
      mounted the root filesystem. The behavior can be overridden
      with the commandline parameter: devtmpfs.mount=0|1.
      This option does not affect initramfs based booting, here
      the devtmpfs filesystem always needs to be mounted manually
      after the rootfs is mounted.
      With this option enabled, it allows to bring up a system in
      rescue mode with init=/bin/sh, even when the /dev directory
      on the rootfs is completely empty.

file_operations

Нарешті, слід створити власний модуль ядра пристрою символів, щоб точно побачити, що відбувається.

Ось мінімальний приклад виконання: Розуміння файлів символьних пристроїв (або спеціальних символів)

Найважливішим кроком є ​​налаштування file_operationsструктури, наприклад:

static const struct file_operations fops = {
    .owner = THIS_MODULE,
    .read = read,
    .open = open,
};

static int myinit(void)
{
    major = register_chrdev(0, NAME, &fops);
    return 0;
}

який містить покажчики функцій, які викликаються для кожного системного виклику, пов'язаного з файлом.

Потім стає очевидним, що ви переосмислюєте ті системні виклики, що стосуються файлів, щоб робити все, що завгодно, і ось так ядро ​​реалізує пристрої, як /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виклику.


У OpenBSD є сценарій MAKEDEV, який трохи спрощує це, дивіться man.openbsd.org/MAKEDEV.8 Не впевнений, чому Linux не має його, за винятком складніше. Можливо, деталі можна було б адаптувати. Наприклад, ви можете сказати MKNOD tty, і він обробляє деталі.
Алан Корі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.