Rivediamo rapidamente i file dei dispositivi: in Linux, i programmi applicativi comunicano le operazioni di rad e scrittura al kernel tramite descrittori di file . Funziona benissimo per i file e si è scoperto che la stessa API poteva essere utilizzata per dispositivi a caratteri che producono e consumano flussi di caratteri e bloccano dispositivi che leggono e scrivono blocchi di dimensioni fisse in un indirizzo di accesso casuale, solo facendo finta che questi sono anche file.
Ma era necessario un modo per configurare quei dispositivi (impostare baud rate ecc.), E per questo fu inventata la chiamata ioctl . Passa semplicemente una struttura di dati specifica per il dispositivo e il tipo di controllo I / O utilizzato per il kernel e recupera i risultati nella stessa struttura di dati, quindi è un'API estensibile molto generica e può essere utilizzata per molte cose .
Ora, come si adattano le operazioni di rete? Una tipica applicazione server di rete desidera associarsi a un determinato indirizzo di rete, ascoltare su una determinata porta (ad esempio 80 per HTTP o 22 per ssh) e, se un client si connette , desidera inviare e ricevere dati da questo client. E le doppie operazioni per il cliente.
Non è ovvio come adattarlo alle operazioni sui file (anche se può essere fatto, vedi Piano 9 ), ecco perché i progettisti UNIX hanno inventato una nuova API: socket . È possibile trovare i dettagli nelle pagine man sezione 2 per socket
, bind
, listen
, connect
, send
e recv
. Si noti che sebbene sia distinto dall'API I / O del file, la socket
chiamata restituisce comunque anche un descrittore di file. Esistono numerosi tutorial su come utilizzare i socket sul Web, google un po '.
Finora questo è un puro UNIX, nessuno parlava di interfacce di rete al momento dell'invenzione dei socket. E poiché questa API è molto vecchia, è definita per una varietà di protocolli di rete oltre il protocollo Internet (guarda le AF_*
costanti), sebbene solo alcuni di questi siano supportati in Linux.
Ma quando i computer hanno iniziato a ottenere più schede di rete, è stata necessaria un'astrazione per questo. In Linux, questa è l' interfaccia di rete (NI). Non viene utilizzato solo per un componente hardware, ma anche per vari tunnel, endpoint dell'applicazione utente che server come tunnel come OpenVPN ecc. Come spiegato, l'API socket non è basata su file (speciali) e indipendenti dal filesystem. Allo stesso modo, neanche le interfacce di rete vengono visualizzate nel file system. Tuttavia, le NI sono rese disponibili nel filesystem /proc
e /sys
(così come in altri parametri sintonizzabili in rete).
Una NI è semplicemente un'astrazione del kernel di un endpoint in cui i pacchetti di rete entrano ed escono dal kernel. I socket, d'altro canto, vengono utilizzati per comunicare i pacchetti con le applicazioni. Nessun socket deve essere coinvolto nell'elaborazione di un pacchetto. Ad esempio, quando l'inoltro è abilitato, un pacchetto può entrare in una NI e partire in un'altra. In tal senso, i socket e le interfacce di rete sono totalmente indipendenti.
Ma doveva esserci un modo per configurare le NI, proprio come avevi bisogno di un modo per configurare i dispositivi a blocchi e caratteri. E poiché i socket hanno già restituito un descrittore di file, era in qualche modo logico consentire solo un ioctl
descrittore su quel file. Questa è l' interfaccia netdevice che hai collegato.
Ci sono molti altri abusi delle chiamate di sistema in modo simile, ad esempio per filtrare i pacchetti, acquisire pacchetti ecc.
Tutto questo è cresciuto pezzo dopo pezzo, e non è particolarmente logico in molti luoghi. Se fosse stato progettato tutto in una volta, probabilmente si sarebbe potuto creare un'API più ortogonale.