unix(7) gniazda lokalnej komunikacji międzyprocesowej

SKŁADNIA

#include <sys/socket.h>
#include <sys/un.h>

unix_socket = socket(AF_UNIX, type, 0);
error = socketpair(AF_UNIX, type, 0, int *sv);

OPIS

Rodzina gniazd AF_UNIX (znana również jako AF_LOCAL) służy do wydajnej komunikacji pomiędzy procesami na tej samej maszynie. Zgodnie z tradycją, gniazda domeny uniksowej mogą być albo anonimowe (tworzone przez socketpair(2)), albo skojarzone z plikiem typu gniazda. Linux wspiera również abstrakcyjną przestrzeń nazw, niezależną od systemu plików.

Poprawne typy to: SOCK_STREAM dla gniazd strumieniowych, SOCK_DGRAM dla gniazd datagramowych, które zachowują granice komunikatów (w przypadku większości implementacji Uniksa gniazda uniksowe są zawsze niezawodne i nie zmieniają kolejności datagramów), oraz (od wersji Linuksa 2.6.4) SOCK_SEQPACKET dla gniazd zorientowanych połączeniowo, które zachowują granice komunikatu i dostarczają komunikaty w kolejności ich wysyłania.

Za pośrednictwem pomocniczych danych można przez gniazda domeny uniksowej przekazywać do innych procesów deskryptory plików i uwierzytelnienia procesów.

Format adresu

Adres gniazda domeny uniksowej jest reprezentowany przez następującą strukturę:
#define UNIX_PATH_MAX    108
struct sockaddr_un {
    sa_family_t sun_family;               /* AF_UNIX */
    char        sun_path[UNIX_PATH_MAX];  /* ścieżka dostępu */
};

sun_family zawsze zawiera AF_UNIX.

W strukturze rozróżniane są trzy typy adresów:

*
pathname: gniazdo domeny uniksowej może zostać związane z zakończoną znakiem NULL nazwą ścieżki systemowej za pomocą bind(2). Jeśli adres gniazda jest zwracany przez getsockname(2), getpeername(2) i accept(2), to jego długością jest


    offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1

a sun_path zawiera nazwę ścieżki zakończoną znakiem NULL.

*
unnamed: Gniazdo strumieniowe nie związane z nazwą ścieżki za pomocą bind(2) nie jest nazwane. Podobnie dwa gniazda utworzone przez socketpair(2) nie są nazwane. Jeśli adres nienazwanego gniazda jest zwracany przez getsockname(2), getpeername(2) i accept(2), to jego długością jest sizeof(sa_family_t), a zawartość sun_path nie powinna być sprawdzana.
*
abstract: adres gniazda abstrakcyjnego jest rozróżniany po tym, że sun_path[0] jest bajtem NULL ("\0"). Adres gniazda znajduje się w przestrzeni nazw podanej w dodatkowych bajtach w sun_path, które są pokryte przez długość struktury adresu (Bajty NULL w nazwie nie mają żadnego specjalnego znaczenia). Nazwa nie ma żadnego powiązania z nazwą pliku w systemie plików. Adres gniazda abstrakcyjnego zwracany przez getsockname(2), getpeername(2) oraz accept(2) ma w polu addrlen ustawioną długość większą niż sizeof(sa_family_t) (tj. większą niż 2), a nazwa gniazda zawarta jest w pierwszych (addrlen - sizeof(sa_family_t)) bajtach pola sun_path. Przestrzeń nazw gniazd abstrakcyjnych jest nieprzenaszalnym rozszerzeniem Linuksa.

Opcje gniazda

Ze względów historycznych następujące opcje gniazd są podawane przy typie SOL_SOCKET, pomimo że są one specyficzne dla AF_UNIX. Można je ustawić za pomocą setsockopt(2), a odczytać za pomocą getsockopt(2), podając SOL_SOCKET jako rodzinę gniazd.
SO_PASSCRED
Włącza otrzymywanie uwierzytelnień od procesu wysyłającego komunikat pomocniczy. Przy włączonej tej opcji i niepołączonym jeszcze gnieździe, unikatowa nazwa gniazda z abstrakcyjnej przestrzeni nazw jest generowana automatycznie. Oczekiwany jest logiczny znacznik typu całkowitego.

Automatyczne przypisywanie adresów

Jeśli w wywołaniu bind(2) podane zostanie addrlen równe sizeof(sa_family_t) lub opcja SO_PASSCRED gniazda była ustawiona dla gniazda nieprzypisanego do adresu, wtedy gniazdo jest automatycznie przypisywane do adresu abstrakcyjnego. Adres ten składa się z bajtu NULL, po którym następuje 5 bajtów ze zbioru znaków [0-9a-f]. W związku z tym liczba automatycznie przypisywanych adresów jest ograniczona przez 2^20. (W Linuksie 2.1.15, w którym dodano możliwość automatycznego przypisywania adresów, i w kolejnych wersjach używane było 8 bajtów, a limit wynosił 2^32 adresów. Zostało to zmienione na 5 bajtów w Linuksie 2.3.15).

API gniazd

W kolejnych paragrafach opisano pewne szczegóły implementacji API gniazd domeny UNIX specyficzne dla Linuksa oraz cechy niewspierane.

Gniazda z domeny uniksowej nie obsługują zawiadomienia o danych autonomicznych (flaga MSG_OOB funkcji send(2) i recv(2)).

Flaga MSG_MORE funkcji send(2) nie jest obsługiwana dla gniazd domeny uniksowej.

Użycie MSG_TRUNC w argumencie flags funkcji recv(2) nie jest obsługiwane dla gniazd domeny uniksowej.

Opcja SO_SNDBUF działa w przypadku gniazd domeny uniksowej, ale opcja SO_RCVBUF już nie. Dla gniazd datagramowych wartość SO_SNDBUF nakłada górny limit na rozmiar wychodzących datagramów. Limit ten jest liczony jako podwojona (patrz socket(7)) wartość opcji minus 32 bajty wymagane na informacje nie będące danymi.

Komunikaty pomocnicze

Dane pomocnicze są wysyłane i odbierane za pomocą sendmsg(2) i recvmsg(2). Ze względów historycznych komunikaty pomocnicze poniższych typów są podawane przy typie SOL_SOCKET, pomimo że są one specyficzne dla AF_UNIX. Aby je wysłać, należy ustawić pole cmsg_level struktury cmsghdr na SOL_SOCKET, a pole cmsg_type na typ. Więcej informacji można znaleźć w cmsg(3).
SCM_RIGHTS
Odbieranie od innego procesu lub wysyłanie do niego zbioru otwartych deskryptorów plików. Porcja danych zawiera tablicę liczb całkowitych będących deskryptorami plików. Przekazane deskryptory plików zachowują się tak, jakby zostały utworzone za pomocą dup(2).
SCM_CREDENTIALS
Odbieranie lub wysyłanie uwierzytelnień uniksowych. Może służyć do autoryzacji. Uwierzytelnienia są przekazywane jako komunikat pomocniczy typu struct ucred, zdefiniowanego w <sys/socket.h> następująco:

struct ucred {
    pid_t pid;  /* identyfikator procesu wysyłającego */
    uid_t uid;  /* ident. użytkownika procesu wysyłającego */
    gid_t gid;  /* ident. grupy procesu wysyłającego */
};

Począwszy od wersji 2.8 biblioteki glibc, aby uzyskać dostęp do definicji powyższej struktury, należy zdefiniować makro _GNU_SOURCE (przed dołączeniem jakichkolwiek plików nagłówkowych).

Jądro sprawdza uwierzytelnienia podane przez wysyłającego. Proces o efektywnym ID użytkownika równym 0 może podać wartości, które różnią się od jego własnych. W pozostałych przepadkach wysyłający musi podać swój własny identyfikator procesu (o ile nie ma ustawionego znacznika CAP_SYS_ADMIN), swój własny identyfikator użytkownika, efektywny identyfikator użytkownika lub ustawiony identyfikator użytkownika (o ile nie ma ustawionego znacznika CAP_SETUID) oraz swój własny identyfikator grupy, efektywny identyfikator grupy lub ustawiony identyfikator grupy (o ile nie ma ustawionego znacznika CAP_SETGID). Aby otrzymać komunikat typu struct ucred, dla gniazda musi być włączona opcja SO_PASSCRED.

Kontrolki systemowe (ioctl)

Następujące wywołania ioctl(2) zwracają informacje w parametrze value. Poprawna składnia to:

int value;
error = ioctl(unix_socket, ioctl_type, &value);

ioctl_type może przyjmować wartość:

SIOCINQ
Zwraca ilość nieprzeczytanych jeszcze danych znajdujących się w kolejce buforu odbierającego. Gniazdo nie może się znajdować w stanie "LISTEN"; w przeciwnym wypadku zostanie zwrócony błąd (EINVAL). SIOCINQ jest zdefiniowany w <linux/sockios.h>. Alternatywnie można użyć synonimu FIONREAD zdefiniowanego w <sys/ioctl.h>.

BŁĘDY

EADDRINUSE
Podany adres lokalny jest zajęty lub obiekt gniazda w systemie plików już istnieje.
ECONNREFUSED
Adres zdalny podany w connect(2) nie odnosił się do gniazda nasłuchującego. Błąd może także wystąpić jeśli nazwa docelowego pliku nie jest gniazdem.
ECONNRESET
Zdalne gniazdo zostało nieoczekiwanie zamknięte.
EFAULT
Nieprawidłowy adres pamięci użytkownika.
EINVAL
Podano nieprawidłowy argument. Najczęstszą przyczyną jest brak ustawionego AF_UNIX w polu sun_type przekazywanych gniazdu adresów lub nieprawidłowy dla danej operacji stan gniazda.
EISCONN
Wywołano connect(2) dla już połączonego gniazda lub podano adres docelowy dla połączonego gniazda.
ENOENT
Nie istnieje ścieżka dla zdalnego adresu przekazanego do connect(2).
ENOMEM
Brak pamięci.
ENOTCONN
Operacja na gnieździe wymaga adresu docelowego, a gniazdo nie jest połączone.
EOPNOTSUPP
Operacja strumieniowa wywołana dla gniazda niestrumieniowego lub próba użycia opcji danych autonomicznych.
EPERM
Wysyłający podał nieprawidłowe uwierzytelnienia w struct ucred.
EPIPE
Zdalne gniazdo strumieniowe zostało zamknięte. Gdy włączone, wysyłany jest jednocześnie sygnał SIGPIPE. Można tego uniknąć, przekazując znacznik MSG_NOSIGNAL do sendmsg(2) lub recvmsg(2).
EPROTONOSUPPORT
Podanym protokołem nie jest AF_UNIX.
EPROTOTYPE
Typ gniazda zdalnego różni się od typu gniazda lokalnego (SOCK_DGRAM wobec SOCK_STREAM)
ESOCKTNOSUPPORT
Nieznany typ gniazda.

Inne błędy mogą zostać wygenerowane przez podstawową warstwę gniazd lub przez system plików podczas tworzenia obiektu gniazda w systemie plików. Więcej informacji można znaleźć na odpowiednich stronach podręcznika.

WERSJE

SCM_CREDENTIALS oraz abstrakcyjna przestrzeń nazw zostały wprowadzone w Linuksie 2.2 i nie należy ich używać w przenośnych programach. (Niektóre systemy wywodzące się z BSD również wspierają przekazywanie uwierzytelnień, ale implementacje różnią się szczegółami).

UWAGI

W linuksowej implementacji dla gniazda widocznych w systemie plików są stosowane uprawnienia katalogu, w którym się znajdują. Ich właściciela, grupę oraz prawa dostępu można zmieniać. Gdy proces nie ma uprawnień do zapisu i przeszukiwania (uruchamiania) do katalogu, w którym tworzone jest gniazdo, jego utworzenie się nie powiedzie. Połączenie z obiektem gniazda wymaga praw odczytu/zapisu. Takie zachowanie różni się od zachowania wielu systemów wywodzących się z BSD, które ignorują uprawnienia dla gniazd uniksowych. Programy przenośne ze względów bezpieczeństwa nie powinny polegać na tej cesze.

W trakcie łączenia się z gniazdem mającym przypisaną nazwę pliku, tworzony jest plik specjalny gniazda w systemie plików, który musi zostać usunięty (za pomocą unlink(2)) przez wywołującego, gdy już nie będzie potrzebny. Stosuje się tu zwykła uniksowa składnia opóźnionego zamknięcia (ang. close-behind): gniazdo można skasować w dowolnym momencie, ale zostanie ono ostatecznie usunięte z systemu plików po zamknięciu ostatniego odwołania do niego.

Aby przekazać deskryptory plików lub uwierzytelnienia poprzez SOCK_STREAM trzeba wysłać/odebrać co najmniej jeden bajt niepomocniczych danych w tym samym wywołaniu sendmsg(2) lub recvmsg(2)

Gniazda strumieniowe z domeny uniksowej nie obsługują zawiadomienia o danych autonomicznych.

PRZYKŁAD

Patrz bind(2).

Przykład użycia SCM_RIGHTS można znaleźć w cmsg(3).

O STRONIE

Angielska wersja tej strony pochodzi z wydania 3.71 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem http://www.kernel.org/doc/man-pages/.

TŁUMACZENIE

Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Andrzej M. Krzysztofowicz (PTM) <[email protected]>, Robert Luberda <[email protected]> i Michał Kułach <[email protected]>.

Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 3.71 oryginału.