Давайте швидко розглянемо файли пристроїв: в Linux прикладні програми передають операції rad і запис в ядро через дескриптори файлів . Це чудово підходить для файлів, і виявилося, що той самий API можна використовувати для символьних пристроїв, які виробляють і споживають потоки символів, і блокують пристрої, які читають і записують блоки фіксованого розміру за випадковою адресою доступу, просто роблячи вигляд, що це також є файли.
Але потрібен спосіб налаштувати ці пристрої (встановити швидкість передачі даних тощо), і для цього був придуманий виклик ioctl . Він просто передає структуру даних, специфічну для пристрою та виду управління введення / виводу, що використовується для ядра, і повертає результати в тій же структурі даних, тому це дуже загальний розширюваний API і може використовуватися для багатьох речей .
Тепер, як підходять мережеві операції? Типова програма мережевого сервера хоче прив’язатись до якоїсь мережевої адреси, прослухати певний порт (наприклад, 80 для HTTP або 22 для ssh), і якщо клієнт підключається , він хоче надсилати дані та отримувати дані від цього клієнта. І подвійні операції для клієнта.
Не очевидно, як це вписати в операції з файлами (хоча це можна зробити, див. План 9 ), тому дизайнери UNIX винайшли новий API: sockets . Ви можете знайти детальну інформацію в довідкових сторінках розділу 2 для socket
, bind
, listen
, connect
, send
і recv
. Зауважте, що він відрізняється від API введення / виводу файлів, але socket
виклик також повертає дескриптор файлу. Існує чимало підручників про те, як користуватися розетками в Інтернеті, трохи гугл.
Поки це все чисто UNIX, ніхто не говорив про мережеві інтерфейси на той час, коли були винайдені розетки. Оскільки цей API справді старий, він визначений для різноманітних мережевих протоколів за межами Інтернет-протоколу (дивіться на AF_*
константи), хоча лише деякі з них підтримуються в Linux.
Але оскільки комп’ютери почали отримувати кілька мережевих карт, для цього знадобилася деяка абстракція. У Linux це мережевий інтерфейс (NI). Він використовується не тільки для обладнання, але і для різних тунелів, кінцевих точок програм для користувачів, які сервіруються як тунелі, такі як OpenVPN і т.д. Таким же чином мережеві інтерфейси також не відображаються у файловій системі. Однак NIs зроблені доступними в /proc
і /sys
файлової системи (а також інші мережеві змінні вручну ).
NI - це проста абстракція ядра кінцевої точки, куди входять мережеві пакети та залишають ядро. З іншого боку, розетки використовуються для зв'язку пакетів із програмами. Жодна розетка не повинна залучатися до обробки пакету. Наприклад, коли переадресація включена, пакет може входити в один NI і залишати на іншому. У цьому сенсі розетки та мережеві інтерфейси абсолютно незалежні.
Але мав бути спосіб конфігурувати NI, як і потрібен спосіб налаштування пристроїв блоків та символів. А оскільки сокети вже повернули дескриптор файлів, було дещо логічно дозволити ioctl
дескриптор цього файлу. Це інтерфейс Netdevice, який ви зв'язали.
Існує досить багато інших зловживань системними дзвінками подібним чином, наприклад, для фільтрації пакетів, захоплення пакетів тощо.
Все це виросло за частиною, і це не особливо логічно в багатьох місцях. Якби все було спроектовано відразу, можливо, можна було б зробити більш ортогональний API.