plucky (7) unix.7.gz

Provided by: manpages-pl_4.25.1-1_all bug

NAZWA

       unix - 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 gniazd w domenie Uniksa 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  pakietów  sekwencyjnych 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ę:

           struct sockaddr_un {
               sa_family_t sun_family;               /* AF_UNIX */
               char        sun_path[108];            /* Ścieżka */
           };

       Pole  sun_family  zawsze  zawiera  AF_UNIX.  W  Linuksie sun_path ma rozmiar 108 bajtów, zob. też USTERKI
       poniżej.

       Różne wywołania systemowe (np. bind(2), connect(2)  i  sendto(2))  przyjmują  argument  sockaddr_un  jako
       wejście.  Niektóre inne wywołania systemowe (np. getsockname(2), getpeername(2), recvfrom(2) i accept(2))
       zwracają argument tego typu.

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

       ścieżka
              gniazdo domeny uniksowej może zostać związane z zakończoną znakiem NULL nazwą  ścieżki  systemowej
              za   pomocą   bind(2).   Jeśli   adres   ścieżki   gniazda   jest  zwracany  (przez  jedno  z  ww.
              wywołań systemowych) to jego długością jest

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

              a sun_path zawiera zakończoną null ścieżkę. (W Linuksie powyższe wyrażenie offsetof()  jest  równe
              tej  samej  wartości  co sizeof(sa_family_t), lecz niektóre inne implementacje dołączają inne pola
              przed sun_path, więc bardziej przenośnie, wyrażenie offsetof() opisuje rozmiar struktury adresu).

              Więcej informacji o ścieżkach gniazd znajduje się poniżej.

       unnamed
              Gniazdo strumieniowe niezwią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, 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  (od adresu ścieżki) 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.  Zwracany
              adres  gniazda  abstrakcyjnego 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.

   Ścieżki gniazd
       Przy   przypisywaniu  gniazda  do  ścieżki  powinno  się przestrzegać  kilku  zasad  w  celu  maksymalnej
       przenośności i łatwości programowania:

       •  Ścieżka w sun_path powinna być zakończona znakiem NULL.

       •  Długość ścieżki, w tym kończący bajt null nie powinna przekraczać rozmiaru sun_path.

       •  Argument addrlen opisujący obejmującą strukturę sockaddr_un powinien mieć wartość przynajmniej:

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

          lub, prościej, addrlen powinien być podany jako sizeof(struct sockaddr_un).

       W różnych implementacjach różnie obsługiwane są adresy  gniazd  domen  Uniksa,  które  nie  przestrzegają
       powyższych  zaleceń.  Na  przykład niektóre (lecz nie wszystkie) implementacje dodają kończący znak null,
       jeśli nie jest on obecny w przekazanej sun_path.

       Przy programowaniu przenośnych aplikacji proszę wziąć pod uwagę, że niektóre implementację mają  sun_path
       o długości zaledwie 92 bajtów.

       Różne  wywołania  systemowe  (accept(2),  recvfrom(2), getsockname(2), getpeername(2)) zwracają struktury
       adresów gniazd. Gdy chodzi o gniazda domeny Uniksa, wartość-rezultat argumentu  addrlen  umieszczonego  w
       wywołaniu  powinna  być zainicjowana  jw. Gdy jest zwracany, argument ten jest ustawiany aby przedstawiać
       aktualny rozmiar struktury adresu. Wywołujący powinien sprawdzić wartość zwracaną w tym argumencie, jeśli
       wartość  wyjściowa przekracza wartość wejściową, to nie ma gwarancji, że kończący znak null jest obecny w
       sun_path (zob PROBLEMY).

   Własność i uprawnienia ścieżki gniazd
       W implementacji  Linuksa,  ścieżki  gniazd  honorują  uprawnienia  katalogów,  w  których  się  znajdują.
       Utworzenie  nowego  gniazda  nie  powiedzie  się,  jeśli  proces  nie  ma uprawnień zapisu i wyszukiwania
       (wykonania) w katalogu, w którym tworzone jest gniazdo.

       W Linuksie, łączenie z gniazdem strumieniowym  wymaga  uprawnień  zapisu  w  stosunku  do  tego  gniazda;
       wysłanie  datagramu  do  gniazda datagramowego również wymaga uprawnień zapisu gniazda. POSIX nie zabiera
       głosu w sprawie efektu uprawnień pliku gniazda i w niektórych  systemach  (np.  starszych  wersjach  BSD)
       uprawnienia  gniazd  są  ignorowane.  Przenośne programy nie powinny opierać się na tym zachowaniu w celu
       zapewnienia bezpieczeństwa.

       Przy tworzeniu nowego gniazda, właściciel  i  grupa  pliku  gniazda  są  ustawiani  zgodnie  ze  zwykłymi
       zasadami. Plik gniazda ma włączone wszystkie uprawnienia, poza tym wyłączonymi przez proces umask(2).

       Właściciela, grupę i uprawnienia ścieżki gniazda można zmienić (za pomocą chown(2) i chmod(2)).

   Gniazda abstrakcyjne
       Uprawnienia  gniazd  nie  mają  znaczenia  dla  gniazd abstrakcyjnych: proces umask(2) nie ma wpływu przy
       kojarzeniu z gniazdem abstrakcyjnym, a zmiana własności  i  uprawnień  obiektu  (za  pomocą  fchown(2)  i
       fchmod(2)) nie wpływa na dostępność gniazda.

       Gniazda abstrakcyjne automatycznie znikają po zamknięciu wszystkich otwartych odniesień do takich gniazd.

       Przestrzeń nazw gniazd abstrakcyjnych jest nieprzenośnym rozszerzeniem systemu Linux.

   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łączenie tej opcji gniazda powoduje przekazanie uwierzytelnień wysyłającego procesu w pomocniczej
              wiadomości SCM_CREDENTIALS, w każdej kolejnej odebranej wiadomości. Zwracanymi  uwierzytelnieniami
              są  te  określone  przez  nadawcę za pomocą SCM_CREDENTIALS lub, jeśli nadawca nie określił danych
              pomocniczych SCM_CREDENTIALS, wartość domyślna  zawierająca:  identyfikator  procesu,  rzeczywisty
              identyfikator użytkownika i rzeczywisty identyfikator grupy nadawcy.

              Przy   włączonej   tej  opcji  i  niepołączonym  jeszcze  gnieździe,  unikatowa  nazwa  gniazda  z
              abstrakcyjnej przestrzeni nazw jest generowana automatycznie.

              Podana wartość jest argumentem do setsockopt(2), a zwracana jako wynik  getsockopt(2)  jest  flaga
              logiczna będąca liczbą całkowitą.

       SO_PASSSEC
              Włącza  odbiór  etykiety  bezpieczeństwa  SELinux  drugiego gniazda w pomocniczym komunikacie typu
              SCM_SECURITY (zob. niżej).

              Podana wartość jest argumentem do setsockopt(2), a zwracana jako wynik  getsockopt(2)  jest  flaga
              logiczna będąca liczbą całkowitą.

              Opcja  SO_PASSSEC  jest  obsługiwana w datagramowych gniazdach domeny uniksowej od Linuksa 2.6.18;
              obsługę w gniazdach strumieniowych domeny uniksowej dodano w jądrze Linux 4.2.

       SO_PEEK_OFF
              Patrz socket(7).

       SO_PEERCRED
              Jest  to  opcja  gniazda  tylko  do  odczytu,  która  zwraca  uwierzytelnienia  drugiego   procesu
              skojarzonego  z  tym  gniazdem. Zwracanymi uwierzytelnieniami są te, które obowiązywały w momencie
              wywołania connect(2), listen(2) lub socketpair(2).

              Argumentem do getsockopt(2) jest wskaźnik do struktury ucred;  należy  zdefiniować  makro  testowe
              _GNU_SOURCE aby pozyskać definicję tej struktury z <sys/socket.h>.

              Opcji  tej  można  używać  wyłącznie  w  połączonych gniazdach strumieniowych AF_UNIX oraz w parze
              gniazda strumieniowego i datagramowego AF_UNIX utworzonej za pomocą socketpair(2).

       SO_PEERSEC
              Ta opcja gniazda tylko do odczytu zwraca kontekst bezpieczeństwa drugiego gniazda  skojarzonego  z
              tym  gniazdem.  Domyślnie  będzie  to  taka  sama wartość jak wartość kontekstu procesu tworzącego
              drugie gniazdo, chyba że zostanie przesłoniona zasadami lub procesem z wymaganymi uprawnieniami.

              Argumentem do getsockopt(2) jest wskaźnik do bufora określonej długości w bajtach, którego łańcuch
              kontekstu  bezpieczeństwa  ma  zostać  skopiowany.  Jeśli długość bufora jest mniejsza niż długość
              łańcucha kontekstu bezpieczeństwa, to getsockopt(2) zwróci -1, ustawi errno  na  ERANGE  i  zwróci
              wymaganą długość za pomocą optlen. Wywołujący powinien początkowo przydzielić co najmniej NAME_MAX
              bajtów dla bufora, choć nie  ma  gwarancji,  że  będzie  to  wielkość  wystarczająca.  Może  zajść
              konieczność dostosowania wielkości bufora do zwróconej długości i wykonanie drugiego podejścia.

              Łańcuch  kontekstu  bezpieczeństwa  może zawierać kończący znak null w zwracanej długości, ale nie
              jest to gwarantowane. Kontekst bezpieczeństwa "foo" może być reprezentowany jako  {'f','o','o'}  o
              długości 3 lub {'f','o','o','\0'} o długości 4, oba te warianty są uważane za równorzędne. Łańcuch
              jest drukowalny, nie zawiera  znaków  null  innych  niż  kończące  łańcuch  oraz  ma  nieokreślone
              kodowanie (w szczególności, nie gwarantuje się kodowania ASCII lub UTF-8).

              Użycie  tej  opcji  do  gniazd  w  rodzinie  adresowej AF_UNIX jest obsługiwane od Linuksa 2.6.2 w
              przypadku  skojarzonych  gniazd  strumieniowych,  a  od  Linuksa  4.18  również  dla  par   gniazd
              strumieniowych i datagramowych utworzonych za pomocą socketpair(2).

   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  do  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.

       Przed  Linuksem  3.4, użycie MSG_TRUNC w argumencie flags funkcji recv(2) nie było 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  niebę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.

              Potocznie,  operacja  ta  jest nazywana "przekazaniem deskryptora pliku" do innego procesu. Jednak
              przyglądając się bliżej, można dostrzec że przekazywana jest referencja do  otwartego  deskryptora
              pliku  (zob.  open(2)),  a  w  procesie  odbierającym  prawdopodobnie  użyty  zostanie  inny numer
              deskryptora pliku. Operacja ta jest semantycznie równoważna duplikacji (dup(2)) deskryptora plików
              na tablicę deskryptora pliku innego procesu.

              Jeśli  bufor  używany  do odebrania danych pomocniczych zawierających deskryptory plików jest zbyt
              mały (lub jest nieobecny),  to  dane  pomocnicze  są  przycinane  (lub  odrzucane),  a  nadmiarowe
              deskryptory plików są automatycznie zamykane przez proces odbierający.

              Jeśli  liczba  deskryptorów plików otrzymana w danych pomocniczych spowodowałaby wykroczenie przez
              proces poza jego limit zasobów RLIMIT_NOFILE (zob. getrlimit(2)), to nadmiarowe deskryptory plików
              zostaną automatycznie zamknięte przez proces odbierający.

              Stała  jądra SCM_MAX_FD określa limit liczby deskryptorów plików w tablicy. Próba wysłania tablicy
              większej od limitu spowoduje błąd EINVAL sendmsg(2). SCM_MAX_FD ma  wartość  253  (lub  255  przed
              Linuksem 2.6.38).

       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  uprzywilejowany  może  podać
              wartości,  które różnią się od jego własnych. W pozostałych przypadkach wysyłający musi podać swój
              własny identyfikator procesu (o ile nie ma ustawionego znacznika CAP_SYS_ADMIN, w przypadku którym
              można  podać identyfikator dowolnego istniejącego procesu), swój własny, rzeczywisty 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.

       SCM_SECURITY
              Otrzymuje  kontekst bezpieczeństwa SELinux (etykietę bezpieczeństwa) drugiego gniazda. Otrzymywane
              dane pomocnicze są łańcuchem zakończonym znakiem null, zawierającym kontekst  bezpieczeństwa.  Dla
              tych  danych  odbiorca powinien przydzielić co najmniej NAME_MAX bajtów w porcji danych komunikatu
              pomocniczego.

              Do otrzymania kontekstu bezpieczeństwa konieczne jest włączenie w gnieździe opcji SO_PASSSEC (zob.
              wyżej).

       Przy  wysyłaniu  danych  pomocniczych  za  pomocą sendmsg(2), w wysłanym komunikacie można podać tylko po
       jednej pozycji dla każdego z powyższych typów.

       Przy wysyłaniu danych pomocniczych konieczne jest przesłanie choć jednego bajta rzeczywistych  danych.  W
       Linuksie  jest  to  wymagane  do poprawnego wysłania danych pomocniczych za pomocą gniazda strumieniowego
       domeny uniksowej. Przy wysyłaniu danych pomocniczych za pomocą gniazda datagramowego domeny uniksowej, na
       Linuksie  nie  ma  konieczności wysyłania jakichkolwiek rzeczywistych danych. Przenośne aplikacje powinny
       jednak również wysyłać choć jeden bajt rzeczywistych danych przy wysyłaniu danych pomocniczych za  pomocą
       gniazda datagramowego.

       Przy  odbieraniu  z  gniazda  strumieniowego,  dane  pomocnicze  stanowią  w  pewien  sposób  barierę dla
       odbieranych danych. Proszę przyjąć przykładowo, że nadawca transmituje:

              (1)  sendmsg(2) o wielkości czterech bajtów, bez danych pomocniczych.
              (2)  sendmsg(2) o wielkości jednego bajta, z danymi pomocniczymi.
              (3)  sendmsg(2) o wielkości czterech bajtów, bez danych pomocniczych.

       Przyjmijmy, że odbiorca wykonuje teraz wywołania recvmsg(2), każde  z  buforem  o  wielkości  20  bajtów.
       Pierwsze  wywołanie  otrzyma  pięć  bajtów  danych,  razem  z  danymi pomocniczymi wysłanymi przez drugie
       wywołanie sendmsg(2). Następne wywołanie otrzyma pozostałe cztery bajty danych.

       Jeśli przestrzeń przydzielona do otrzymywanych danych pomocniczych jest zbyt mała, to dane pomocnicze  są
       przycinane  do  liczby  nagłówków  mieszczących  się  w  udostępnionym  buforze  (lub,  w przypadku listy
       deskryptora  pliku  SCM_RIGHTS,  sama  lista  deskryptorów  pliku  może  zostać  przycięta).  Jeśli   dla
       przychodzących  danych  pomocniczych  nie  udostępniono  bufora  (np.  pole  msg_control struktury msghdr
       przekazanej do recvmsg(2) wynosi NULL),  to  przychodzące  dane  pomocnicze  są  odrzucane.  W  obu  tych
       przypadkach, flaga MSG_CTRUNC zostanie ustawiona na wartość msg.msg_flags zwróconą przez recvmsg(2).

   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
              Dla  gniazd  SOCK_STREAM,  wywołanie to zwraca liczbę nieprzeczytanych jeszcze bajtów znajdujących
              się w buforze odbierającym. 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>.  Dla  gniazd  SOCK_DGRAM,  zwracana
              wartość jest taka sama jak w przypadku datagramowych gniazd domeny Internet; zob. udp(7).

BŁĘDY

       EADDRINUSE
              Podany adres lokalny jest zajęty lub obiekt gniazda w systemie plików już istnieje.

       EBADF  Błąd  może  zajść  dla  sendmsg(2),  przy  wysyłaniu  deskryptora  pliku  jako  dane pomocnicze za
              pośrednictwem gniazda domeny uniksowej (zob. opis SCM_RIGHTS wyżej) i wskazuje  że  wysłany  numer
              deskryptora pliku jest nieprawidłowy (np. nie jest to otwarty deskryptor pliku).

       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 docelowa ścieżka 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.

       ENFILE Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.

       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 send(2) lub sendmsg(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.

       ESRCH  Przy   wysyłaniu   komunikatów   pomocniczych  zawierających  uwierzytelnienie  (SCM_CREDENTIALS),
              wywołujący podał identyfikator procesu, który nie dopasował żadnego istniejącego procesu.

       ETOOMANYREFS
              Błąd może zajść  dla  sendmsg(2),  przy  wysyłaniu  deskryptora  pliku  jako  dane  pomocnicze  za
              pośrednictwem  gniazda  domeny  uniksowej  (zob.  opis  SCM_RIGHTS wyżej). Występuje, jeśli liczba
              deskryptorów pliku "w locie" wykracza poza limit zasobów RLIMIT_NOFILE, a wywołujący  nie  posiada
              przywileju  CAP_SYS_RESOURCE.  Przez  deskryptor  pliku  w  locie  rozumiemy tu taki, który został
              wysłany za pomocą sendmsg(2), ale nie został jeszcze zaakceptowany przez proces docelowy za pomocą
              recvmsg(2).

              Błąd  ten  jest  diagnozowany w głównej gałęzi jądra od Linuksa 4.5 (i w niektórych wcześniejszych
              wersjach, gdzie zaaplikowano odpowiednią łatkę). We  wcześniejszych  wersjach  jądra,  można  było
              umieścić  nieograniczoną  liczbę  deskryptorów  plików w locie, poprzez wysłanie każdego z nich za
              pomocą sendmsg(2), a następnie zamknięcie deskryptora pliku,  co  nie  liczyło  się  wobec  limitu
              zasobów RLIMIT_NOFILE.

       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  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.

USTERKI

       Przy wiązaniu gniazda z adresem, Linux jest jedną z implementacji dodających  kończące  null,  jeśli  nie
       poda  się  go  w  sun_path.  Zwykle jest to bezproblemowe, gdy adres gniazda jest pozyskiwany będzie on o
       jeden bajt dłuższy niż  podawany  początkowo.  Jest  jednak  jeden  przypadek  mogący  spowodować  mylące
       zachowanie:  jeśli podany zostanie adres 108 bajtowy, bez znaku null, to dodanie znaku null spowodowałoby
       przekroczenie długości ścieżki poza sizeof(sun_path). W konsekwencji, przy  pozyskiwaniu  adresu  gniazda
       (np.  poprzez  accept(2)),  jeśli wejściowy argument addrlen dla pozyskiwanego wywołania jest podany jako
       sizeof(struct sockaddr_un), to zwrócona struktura adresu nie będzie miała kończącego null w sun_path.

       Dodatkowo, niektóre implementacje nie wymagają kończącego null przy wiązaniu  gniazda  (argument  addrlen
       jest  używany  do  określenia  długości  sun_path),  a  gdy w tych implementacjach jest pozyskiwany adres
       gniazda, to nie ma kończącego null w sun_path.

       Aplikacje pozyskujące adresy gniazd mogą posiadać (przenośny) kod do obsługi możliwości,  że  w  sun_path
       nie ma kończącego null zauważając fakt, że liczba prawidłowych bajtów w ścieżce to:

           strnlen(addr.sun_path, addrlen - offsetof(sockaddr_un, sun_path))

       Alternatywnie, aplikacja może pozyskać adres gniazda przez przydzielenie buforu o rozmiarze sizeof(struct
       sockaddr_un)+1 który jest wyzerowany przed pozyskaniem. Pobierające wywołanie może określić addrlen  jako
       sizeof(struct  sockaddr_un),  a  dodatkowy  bajt zero zapewnia, że w łańcuchu zwróconym w sun_path będzie
       kończące null:

           void *addrp;

           addrlen = sizeof(struct sockaddr_un);
           addrp = malloc(addrlen + 1);
           if (addrp == NULL)
               /* Obsługa błędu */ ;
           memset(addrp, 0, addrlen + 1);

           if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
               /* obsługa błędu */ ;

           printf("sun_path = %s\n", ((struct sockaddr_un *) addrp)->sun_path);

       Tego bałaganu można uniknąć, jeśli jest pewność, że aplikacja tworząca ścieżki gniazd  przestrzega  reguł
       opisanych powyżej rozdziale Ścieżki gniazd.

PRZYKŁADY

       Poniższy  kod  demonstruje użycie gniazd pakietów sekwencyjnych do lokalnej komunikacji międzyprocesowej.
       Składa się z dwóch programów. Serwer czeka na połączenie z programu klienckiego. Klient wysyła  każdy  ze
       swoich  argumentów  wiersza  poleceń w oddzielnych wiadomościach. Serwer traktuje przychodzące wiadomości
       jako liczby całkowite i dodaje je.  Klient  wysyła  łańcuch  polecenia  "END".  Serwer  odsyła  komunikat
       zawierający  sumę  klienckich  liczb  całkowitych.  Klient  wypisuje  sumę  i  wychodzi.  Serwer czeka na
       połączenie od kolejnego klienta. Aby  zatrzymać serwer,  klient  jest  wywoływany  z  argumentem  wiersza
       poleceń "DOWN".

       Podczas  działania  serwera  w  tle  i  kolejnych  uruchomień klienta zarejestrowano następujące wyjście.
       Wykonywanie programu serwera kończy się, gdy otrzymuje on polecenie "DOWN".

   Przykładowe wyjście
           $ ./server &
           [1] 25887
           $ ./client 3 4
           Wynik = 7
           $ ./client 11 -5
           Wynik = 6
           $ ./client DOWN
           Wynik = 0
           [1]+  Done                    ./server
           $

   Kod źródłowy programu

       /*
        * Plik connection.h
        */
       #ifndef CONNECTION_H
       #define CONNECTION_H

       #define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
       #define BUFFER_SIZE 12

       #endif  // include guard (ochr. przed wielokr. przetw.)

       /*
        * Plik server.c
        */

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/types.h>
       #include <sys/un.h>
       #include <unistd.h>

       #include "connection.h"

       int
       main(void)
       {
           int                 down_flag = 0;
           int                 ret;
           int                 connection_socket;
           int                 data_socket;
           int                 result;
           ssize_t             r, w;
           struct sockaddr_un  name;
           char                buffer[BUFFER_SIZE];

           /* Tworzenie gniazda lokalnego. */

           connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (connection_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Ze względu na przenośność konieczne jest wyczyszczenie całej
            * struktury, ponieważ niektóre implementacje zawierają dodatkowe
            * (nieprzenośne) pola w strukturze.
            */

           memset(&name, 0, sizeof(name));

           /* Skojarzenie gniazda z nazwą gniazda. */

           name.sun_family = AF_UNIX;
           strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);

           ret = bind(connection_socket, (const struct sockaddr *) &name,
                      sizeof(name));
           if (ret == -1) {
               perror("bind");
               exit(EXIT_FAILURE);
           }

           /*
            * Przygotowanie do przyjmowania połączeń. Rozmiar dziennika zaległości
            * ustawiony na 20. W trakcie przetwarzania jednego żądania, inne mogą
            * zatem oczekiwać.
            */

           ret = listen(connection_socket, 20);
           if (ret == -1) {
               perror("listen");
               exit(EXIT_FAILURE);
           }

           /* To jest główna pętla do obsługi połączeń. */

           for (;;) {

               /* Oczekiwanie na połączenie przychodzące. */

               data_socket = accept(connection_socket, NULL, NULL);
               if (data_socket == -1) {
                   perror("accept");
                   exit(EXIT_FAILURE);
               }

               result = 0;
               for (;;) {

                   /* Oczekiwanie na następny pakiet danych. */

                   r = read(data_socket, buffer, sizeof(buffer));
                   if (r == -1) {
                       perror("read");
                       exit(EXIT_FAILURE);
                   }

                   /* Upewnienie się, że bufor jest zakończony 0. */

                   buffer[sizeof(buffer) - 1] = 0;

                   /* Obsługa poleceń. */

                   if (!strncmp(buffer, "DOWN", sizeof(buffer))) {
                       down_flag = 1;
                       continue;
                   }

                   if (!strncmp(buffer, "END", sizeof(buffer))) {
                       break;
                   }

                   if (down_flag) {
                       continue;
                   }

                   /* Dodanie otrzymanego składnika. */

                   result += atoi(buffer);
               }

               /* Wysłanie wyniku. */

               sprintf(buffer, "%d", result);
               w = write(data_socket, buffer, sizeof(buffer));
               if (w == -1) {
                   perror("write");
                   exit(EXIT_FAILURE);
               }

               /* Zamknięcie gniazda. */

               close(data_socket);

               /* Wyjście na polecenie DOWN. */

               if (down_flag) {
                   break;
               }
           }

           close(connection_socket);

           /* Odlinkowanie gniazda. */

           unlink(SOCKET_NAME);

           exit(EXIT_SUCCESS);
       }

       /*
        * Plik client.c
        */

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/types.h>
       #include <sys/un.h>
       #include <unistd.h>

       #include "connection.h"

       int
       main(int argc, char *argv[])
       {
           int                 ret;
           int                 data_socket;
           ssize_t             r, w;
           struct sockaddr_un  addr;
           char                buffer[BUFFER_SIZE];

           /* Tworzenie gniazda lokalnego. */

           data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (data_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Ze względu na przenośność konieczne jest wyczyszczenie całej
            * struktury, ponieważ niektóre implementacje zawierają dodatkowe
            * (nieprzenośne) pola w strukturze.
            */

           memset(&addr, 0, sizeof(addr));

           /* Łączenie gniazda z adresem gniazda. */

           addr.sun_family = AF_UNIX;
           strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);

           ret = connect(data_socket, (const struct sockaddr *) &addr,
                          sizeof(addr));
           if (ret == -1) {
               fprintf(stderr, "Serwer jest wyłączony.\n");
               exit(EXIT_FAILURE);
           }

           /* Wysyłanie argumentów. */

           for (int i = 1; i < argc; ++i) {
               w = write(data_socket, argv[i], strlen(argv[i]) + 1);
               if (w == -1) {
                   perror("write");
                   break;
               }
           }

           /* Żądanie wyniku. */

           strcpy(buffer, "END");
           w = write(data_socket, buffer, strlen(buffer) + 1);
           if (w == -1) {
               perror("write");
               exit(EXIT_FAILURE);
           }

           /* Otrzymanie wyniku. */

           r = read(data_socket, buffer, sizeof(buffer));
           if (r == -1) {
               perror("read");
               exit(EXIT_FAILURE);
           }

           /* Upewnienie się, że bufor kończy się 0. */

           buffer[sizeof(buffer) - 1] = 0;

           printf("Wynik = %s\n", buffer);

           /* Zamknięcie gniazda. */

           close(data_socket);

           exit(EXIT_SUCCESS);
       }

       Przykłady użycia SCM_RIGHTS można znaleźć w podręcznikach cmsg(3) i seccomp_unotify(2).

ZOBACZ TAKŻE

       recvmsg(2), sendmsg(2), socket(2), socketpair(2), cmsg(3),  capabilities(7),  credentials(7),  socket(7),
       udp(7)

TŁUMACZENIE

       Autorami    polskiego    tłumaczenia   niniejszej   strony   podręcznika   są:   Andrzej   Krzysztofowicz
       <ankry@green.mf.pg.gda.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

       Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje  o  warunkach  licencji  można  uzyskać
       zapoznając  się  z  GNU General Public License w wersji 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ lub
       nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

       Błędy w tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej  ⟨manpages-pl-
       list@lists.sourceforge.net⟩.