Szybko przejrzyjmy pliki urządzeń: w Linuksie aplikacje komunikują się z jądrem i zapisują operacje do jądra poprzez deskryptory plików . Działa to świetnie w przypadku plików i okazało się, że ten sam interfejs API może być używany do urządzeń znakowych, które wytwarzają i konsumują strumienie znaków oraz blokują urządzenia, które odczytują i zapisują bloki o stałym rozmiarze pod losowym adresem dostępu, udając, że te są również plikami.
Potrzebny był jednak sposób na skonfigurowanie tych urządzeń (ustawienie szybkości transmisji itp.), W tym celu wymyślono wywołanie ioctl . Po prostu przekazuje strukturę danych specyficzną dla urządzenia i rodzaj kontroli we / wy używanej do jądra, i zwraca wyniki w tej samej strukturze danych, więc jest to bardzo ogólny rozszerzalny interfejs API i może być używany do wielu rzeczy .
Jak pasują operacje sieciowe? Typowa aplikacja serwera sieciowego chce powiązać się z jakimś adresem sieciowym, nasłuchiwać na określonym porcie (np. 80 dla HTTP lub 22 dla ssh), a jeśli klient się łączy , chce wysyłać dane i odbierać dane od tego klienta. I podwójne operacje dla klienta.
Nie jest oczywiste, jak dopasować to do operacji na plikach (choć można to zrobić, patrz Plan 9 ), dlatego projektanci UNIX wymyślili nowe API: gniazda . Szczegóły można znaleźć na stronach sekcja 2 MAN na socket
, bind
, listen
, connect
, send
i recv
. Należy zauważyć, że chociaż różni się od interfejsu API we / wy pliku, socket
wywołanie zwraca jednak również deskryptor pliku. Istnieje wiele samouczków na temat korzystania z gniazd w Internecie, trochę google.
Jak dotąd wszystko to jest czystym systemem UNIX, nikt nie mówił o interfejsach sieciowych w momencie wynalezienia gniazd. Ponieważ ten interfejs API jest naprawdę stary, został zdefiniowany dla różnych protokołów sieciowych poza protokołem internetowym (spójrz na AF_*
stałe), chociaż tylko kilka z nich jest obsługiwanych w systemie Linux.
Ale ponieważ komputery zaczęły otrzymywać wiele kart sieciowych, potrzebna była do tego abstrakcja. W systemie Linux jest to interfejs sieciowy (NI). Jest używany nie tylko do sprzętu, ale także do różnych tuneli, punktów końcowych aplikacji użytkownika, które serwują jako tunele takie jak OpenVPN itp. Jak wyjaśniono, API gniazda nie jest oparte na (specjalnych) plikach i niezależne od systemu plików. W ten sam sposób interfejsy sieciowe również nie są wyświetlane w systemie plików. Jednak NI są udostępniane w systemie plików /proc
i /sys
(jak również w innych tunelach sieciowych).
NI to prosta abstrakcja jądra punktu końcowego, w którym pakiety sieciowe wchodzą i wychodzą z jądra. Z drugiej strony gniazda służą do komunikacji pakietów z aplikacjami. Przetwarzanie pakietu nie wymaga udziału żadnego gniazda. Na przykład, gdy włączone jest przekazywanie, pakiet może wejść na jeden NI i pozostawić na innym. W tym sensie gniazda i interfejsy sieciowe są całkowicie niezależne.
Ale musiał istnieć sposób na skonfigurowanie NI, tak jak potrzebny byłby sposób skonfigurowania urządzeń blokowych i znakowych. A ponieważ gniazda już zwróciły deskryptor pliku, logiczne było po prostu zezwolenie ioctl
na deskryptor pliku. To jest interfejs sieciowy , który połączyłeś.
Istnieje wiele innych nadużyć wywołań systemowych w podobny sposób, na przykład do filtrowania pakietów, przechwytywania pakietów itp.
Wszystko to rosło kawałek po kawałku i nie jest szczególnie logiczne w wielu miejscach. Gdyby został zaprojektowany od razu, prawdopodobnie można by stworzyć bardziej ortogonalny interfejs API.