Provided by: manpages-pl_4.23.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⟩.