.\" -*- coding: UTF-8 -*-
.\" Copyright 1993 Giorgio Ciucci (giorgio@crcc.it)
.\" and Copyright 2020 Michael Kerrisk <mtk.manpages@gmail.com>
.\"
.\" SPDX-License-Identifier: Linux-man-pages-copyleft
.\"
.\" Modified Sun Nov 28 17:06:19 1993, Rik Faith (faith@cs.unc.edu)
.\"          with material from Luigi P. Bai (lpb@softint.com)
.\" Portions Copyright 1993 Luigi P. Bai
.\" Modified Tue Oct 22 22:04:23 1996 by Eric S. Raymond <esr@thyrsus.com>
.\" Modified, 5 Jan 2002, Michael Kerrisk <mtk.manpages@gmail.com>
.\" Modified, 19 Sep 2002, Michael Kerrisk <mtk.manpages@gmail.com>
.\"	Added SHM_REMAP flag description
.\" Modified, 27 May 2004, Michael Kerrisk <mtk.manpages@gmail.com>
.\"     Added notes on capability requirements
.\" Modified, 11 Nov 2004, Michael Kerrisk <mtk.manpages@gmail.com>
.\"	Language and formatting clean-ups
.\"	Changed wording and placement of sentence regarding attachment
.\"		of segments marked for destruction
.\"
.\"*******************************************************************
.\"
.\" This file was generated with po4a. Translate the source file.
.\"
.\"*******************************************************************
.TH SHMOP 2 "15 czerwca 2024 r." "Linux man\-pages 6.9.1" 
.SH NAZWA
shmat, shmdt \- operacje na segmentach pamięci dzielonej Systemu V
.SH BIBLIOTEKA
Standardowa biblioteka C (\fIlibc\fP, \fI\-lc\fP)
.SH SKŁADNIA
.nf
\fB#include <sys/shm.h>\fP
.P
\fBvoid *shmat(int \fP\fIshmid\fP\fB, const void *_Nullable \fP\fIshmaddr\fP\fB, int \fP\fIshmflg\fP\fB);\fP
\fBint shmdt(const void *\fP\fIshmaddr\fP\fB);\fP
.fi
.SH OPIS
.SS shmat()
\fBshmat\fP() dołącza segment pamięci dzielonej Systemu\ V identyfikowany przez
\fIshmid\fP do przestrzeni adresowej procesu, który ją wywołał. Adres, pod
którym segment ma być widoczny jest przekazywany w parametrze \fIshmaddr\fP,
przy czym system może przetworzyć ten adres w następujący sposób:
.IP \[bu] 3
Jeśli \fIshmaddr\fP jest równy NULL, to system sam wybierze odpowiedni
wyrównany do rozmiaru strony (nieużywany) adres, pod którym segment będzie
widoczny.
.IP \[bu]
Jeśli \fIshmaddr\fP jest różny od NULL i w \fIshmflg\fP przekazany został znacznik
\fBSHM_RND\fP, wówczas segment zostanie dołączony pod adresem \fIshmaddr\fP
zaokrąglonym w dół do wielokrotności \fBSHMLBA\fP.
.IP \[bu]
W innym przypadku \fIshmaddr\fP musi być wyrównanym do granicy strony adresem,
pod którym nastąpi dołączenie segmentu.
.P
Oprócz \fBSHM_RND\fP można określić następujące znaczniki w argumencie maski
bitowej \fIshmflg\fP:
.TP 
\fBSHM_EXEC\fP (charakterystyczne dla Linuksa; od Linuksa w wersji 2.6.9)
Pozwala na wykonanie zawartości segmentu. Wywołujący musi mieć prawo
wykonania segmentu.
.TP 
\fBSHM_RDONLY\fP
Dołącza segment do dostępu tylko do odczytu. Proces wywołujący musi mieć
prawa odczytu segmentu.  Jeśli znacznik nie jest określona, w dołączanym
segmencie możliwy jest dostęp do odczytu jak i zapisu, przy czym proces musi
mieć prawa do odczytu i zapisu segmentu. Nie istnieje pojęcie segmentu
pamięci dzielonej tylko do zapisu.
.TP 
\fBSHM_REMAP\fP (charakterystyczne dla Linuksa)
Ten znacznik oznacza, że odwzorowanie tego segmentu powinno zastąpić
jakiekolwiek istniejące wcześniej odwzorowanie w zakresie rozpoczynającym
się od \fIshmaddr\fP i rozciągającym się na rozmiar segmentu. (Normalnie, gdy
odwzorowanie w tym zakresie adresów już istnieje, powinien wystąpić błąd
\fBEINVAL\fP). W tym przypadku \fIshmaddr\fP nie może być równy NULL.
.P
Wartość \fBbrk\fP(2) procesu wywołującego nie jest zmieniana podczas dołączania
segmentu. Segment zostanie automatycznie odłączony, gdy proces się
zakończy. Ten sam segment może być dołączony do przestrzeni adresowej
procesu jako \[Bq]tylko do odczytu\[rq] lub \[Bq]do odczytu i zapisu\[rq]
więcej niż raz.
.P
Pomyślne wywołanie \fBshmdt\fP aktualizuje pola struktury \fIshmid_ds\fP (patrz
\fBshmctl\fP(2)) opisującej segment w następujący sposób:
.IP \[bu] 3
\fIshm_atime\fP przypisywany jest bieżący czas.
.IP \[bu]
\fIshm_lpid\fP jest ustawiane na identyfikator procesu wywołującego.
.IP \[bu]
.\"
\fIshm_nattch\fP jest zwiększane o jeden.
.SS shmdt()
\fBshmdt\fP odłącza segment pamięci dzielonej odwzorowany pod adresem podanym w
\fIshmaddr\fP z przestrzeni adresowej procesu wywołującego tę
funkcję. Przekazany funkcji w parametrze \fIshmaddr\fP adres musi być równy
adresowi zwróconemu wcześniej przez wywołanie \fBshmat\fP().
.P
Pomyślne wywołanie \fBshmdt\fP aktualizuje pola struktury \fIshmid_ds\fP
opisującej segment w następujący sposób:
.IP \[bu] 3
\fIshm_dtime\fP przypisywany jest bieżący czas.
.IP \[bu]
\fIshm_lpid\fP jest ustawiane na identyfikator procesu wywołującego.
.IP \[bu]
\fIshm_nattch\fP jest zmniejszane o jeden. Jeśli pole to osiągnie 0 i segment
jest zaznaczony do usunięcia, wówczas zostanie on usunięty.
.SH "WARTOŚĆ ZWRACANA"
Jeśli się powiedzie, \fBshmat\fP() zwraca adres dołączonego segmentu pamięci
dzielonej; w razie błędu zwracane jest \fI(void\ *)\ \-1\fP, a zmienna \fIerrno\fP
wskazuje błąd.
.P
Jeśli się powiedzie, \fBshmdt\fP() zwraca 0; w razie błędu zwracane jest \-1, a
zmienna \fIerrno\fP wskazuje błąd.
.SH BŁĘDY
\fBshmat\fP() może zawieść z powodu następujących błędów:
.TP 
\fBEACCES\fP
Proces wywołujący nie ma wystarczających uprawnień do dołączenia segmentu w
żądany sposób oraz nie ma przywileju \fBCAP_IPC_OWNER\fP (ang. capability) w
tej przestrzeni nazw użytkownika, która odpowiada za przestrzeń nazw IPC.
.TP 
\fBEIDRM\fP
\fIshmid\fP wskazuje na usunięty identyfikator.
.TP 
\fBEINVAL\fP
Niewłaściwa wartość parametru \fIshmid\fP, niewyrównana (do granicy strony i
nie podano \fBSHM_RND\fP) lub niepoprawna wartość \fIshmaddr\fP albo nieudane
dołączenie pod adresem \fIshmaddr\fP lub został podany znacznik \fBSHM_REMAP\fP,
podczas gdy \fIshmaddr\fP było równe NULL.
.TP 
\fBENOMEM\fP
Brak pamięci na deskryptor lub tablice stron.
.P
\fBshmdt\fP() może zawieść z powodu następujących błędów:
.TP 
\fBEINVAL\fP
.\" The following since Linux 2.6.17-rc1:
Żaden segment pamięci dzielonej nie jest podłączony pod adresem \fIshmaddr\fP
lub \fIshmaddr\fP nie jest wyrównany do granicy strony.
.SH STANDARDY
POSIX.1\-2008.
.SH HISTORIA
.\" SVr4 documents an additional error condition EMFILE.
POSIX.1\-2001, SVr4.
.P
W SVID 3 (lub być może wcześniejszym) typ parametru \fIshmaddr\fP został
zmieniony z \fIchar\ *\fP na \fIconst void\ *\fP, a typ wyniku zwracanego przez
\fBshmat\fP() z \fIchar\ *\fP na \fIvoid\ *\fP.
.SH UWAGI
W wyniku wywołania \fBfork\fP(2) proces potomny dziedziczy dołączone segmenty
pamięci dzielonej.
.P
Po wykonaniu \fBexec\fP(2) wszystkie dołączone segmenty pamięci dzielonej są
odłączane od procesu.
.P
Po wykonaniu \fB_exit\fP(2) wszystkie dołączone segmenty pamięci dzielonej są
odłączane od procesu.
.P
Używanie \fBshmat\fP() z \fIshmaddr\fP równym NULL jest zalecaną i przenośną
metodą dołączania segmentu pamięci dzielonej. Trzeba jednak być świadomym,
że ta metoda dołączania segmentu pamięci dzielonej może spowodować jego
dołączenie pod różnymi adresami w różnych procesach.  W związku z tym
wszystkie wskaźniki obsługiwane w pamięci dzielonej muszą być względne
(zazwyczaj względem adresu początkowego segmentu), nie zaś bezwzględne.
.P
Linux pozwala na dołączenie segmentu pamięci dzielonej, nawet jeśli już
został zaznaczony do usunięcia. Jednakże POSIX.1 nie określa takiego
zachowania i wiele innych implementacji go nie obsługuje.
.P
Na wywołanie \fBshmat\fP() wpływa następujący parametr systemowy:
.TP 
\fBSHMLBA\fP
Wielokrotność dolnej granicy adresu segmentu. Podczas bezpośredniego
wskazania dołączonego adresu w wywołaniu do \fBshmat\fP(), wywołujący powinien
się upewnić, że adres jest wielokrotnością tej wartości. Jest to konieczne w
przypadku niektórych architektur, aby zapewnić dobrą wydajność pamięci
podręcznej procesora lub aby zapewnić, że różne dołączenia tego samego
segmentu mają spójne widoki w pamięci podręcznej procesora. \fBSHMLBA\fP jest
zwykle jakąś wielokrotnością systemowego rozmiaru strony. (W wielu
architekturach linuksowych wartość \fBSHMLBA\fP jest taka sama, jak systemowy
rozmiar strony).
.P
Aktualna implementacja nie ma wewnętrznego ograniczenia na liczbę segmentów
pamięci dzielonej dołączanych do jednego procesu (\fBSHMSEG\fP).
.SH PRZYKŁADY
Dwa programy pokazane poniżej, wymieniają łańcuch za pomocą segmentu pamięci
dzielonej. Więcej szczegółów na temat programów podano poniżej. Na początku
zademonstrujmy sesję powłoki pokazującą działanie programów.
.P
W jednym oknie terminala, uruchamiamy program \[Bq]odczytujący\[rq], który
tworzy segment pamięci dzielonej Systemu\ V oraz zestaw semaforów Systemu\ V. Program wypisuje identyfikatory dzielonych obiektów, a następnie oczekuje
na zmianę wartości przez semafor.
.P
.in +4n
.EX
$ \fB./svshm_string_read\fP
shmid = 1114194; semid = 15
.EE
.in
.P
W drugim oknie terminala, uruchamiamy program
\[Bq]zapisujący\[rq]. Przyjmuje on trzy argumenty w wierszu polecenia:
identyfikatory: segmentu pamięci dzielonej i zestawu semaforów utworzone
przez program \[Bq]odczytujący\[rq] oraz łańcuch. Dołącza on istniejący
segment pamięci dzielonej, kopiuje łańcuch do pamięci dzielonej i modyfikuje
wartość semafora.
.P
.in +4n
.EX
$ \fB./svshm_string_write 1114194 15 \[aq]Witaj świecie!\[aq]\fP
.EE
.in
.P
Powracając do terminala, gdzie działa program \[Bq]odczytujący\[rq] widzimy,
że program przestał oczekiwać na semafor i wypisał łańcuch, który został
skopiowany do segmentu pamięci dzielonej przez program \[Bq]zapisujący\[rq]:
.P
.in +4n
.EX
Witaj świecie!
.EE
.in
.\"
.SS "Kod źródłowy: svshm_string.h"
Poniższy plik nagłówkowy jest dołączany przez programy:
\[Bq]odczytujący\[rq] i \[Bq]zapisujący\[rq]:
.P
.in +4n
.\" SRC BEGIN (svshm_string.h)
.EX
/* svshm_string.h
\&
   Na licencji GNU General Public License v2 lub późniejszej.
*/
#ifndef SVSHM_STRING_H
#define SVSHM_STRING_H
\&
#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h>
\&
#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \[rs]
                        } while (0)
\&
union semun {                   /* Używane w wywołaniach do semctl() */
    int                 val;
    struct semid_ds     *buf;
    unsigned short      *array;
#if defined(__linux__)
    struct seminfo      *__buf;
#endif
};
\&
#define MEM_SIZE 4096
\&
#endif  // include guard (ochr. przed wielokr. przetw.)
.EE
.\" SRC END
.in
.\"
.SS "Kod źródłowy programu: svshm_string_read.c"
Program \[Bq]odczytujący\[rq] tworzy segment pamięci dzielonej i zestaw
semaforów, zawierający jeden semafor. Następnie dołącza obiekt pamięci
dzielonej do swojej przestrzeni adresowej i inicjuje wartość semafora na
1. Na końcu, oczekuje na przyjęcie przez semafor wartości 0; wówczas
wypisuje łańcuch, który został skopiowany do segmentu pamięci dzielonej
przez program \[Bq]zapisujący\[rq].
.P
.in +4n
.\" SRC BEGIN (svshm_string_read.c)
.EX
/* svshm_string_read.c
\&
   Na licencji GNU General Public License v2 lub późniejszej.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
\&
#include "svshm_string.h"
\&
int
main(void)
{
    int            semid, shmid;
    char           *addr;
    union semun    arg, dummy;
    struct sembuf  sop;
\&
    /* Utworzenie pamięci dzielonej i zestawu semaforów, zawierającego
       jeden semafor. */
\&
    shmid = shmget(IPC_PRIVATE, MEM_SIZE, IPC_CREAT | 0600);
    if (shmid == \-1)
        errExit("shmget");
\&
    semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
    if (semid == \-1)
        errExit("semget");
\&
    /* Dołączenie pamięci dzielonej do naszej przestrzeni adresowej. */
\&
    addr = shmat(shmid, NULL, SHM_RDONLY);
    if (addr == (void *) \-1)
        errExit("shmat");
\&
    /* Zainicjowanie semafora 0 w zestawie, z wartością 1. */
\&
    arg.val = 1;
    if (semctl(semid, 0, SETVAL, arg) == \-1)
        errExit("semctl");
\&
    printf("shmid = %d; semid = %d\[rs]n", shmid, semid);
\&
    /* Oczekiwanie na przyjęcie przez semafor wartości 0. */
\&
    sop.sem_num = 0;
    sop.sem_op = 0;
    sop.sem_flg = 0;
\&
    if (semop(semid, &sop, 1) == \-1)
        errExit("semop");
\&
    /* Wypisanie łańcucha z pamięci dzielonej. */
\&
    printf("%s\[rs]n", addr);
\&
    /* Usunięcie pamięci dzielonej i zestawu semaforów. */
\&
    if (shmctl(shmid, IPC_RMID, NULL) == \-1)
        errExit("shmctl");
    if (semctl(semid, 0, IPC_RMID, dummy) == \-1)
        errExit("semctl");
\&
    exit(EXIT_SUCCESS);
}
.EE
.\" SRC END
.in
.\"
.SS "Kod źródłowy programu: svshm_string_write.c"
Program \[Bq]zapisujący\[rq] przyjmuje trzy argumenty w wierszu polecenia:
identyfikatory: segmentu pamięci dzielonej i zestawu semaforów utworzone
przez program \[Bq]odczytujący\[rq] oraz łańcuch. Dołącza on istniejący
segment pamięci dzielonej do swojej przestrzeni adresowej i zmniejsza
wartość semafora na 0, w celu poinformowania programu
\[Bq]odczytującego\[rq], że może on teraz sprawdzić zawartość pamięci
dzielonej.
.P
.in +4n
.\" SRC BEGIN (svshm_string_write.c)
.EX
/* svshm_string_write.c
\&
   Na licencji GNU General Public License v2 lub późniejszej.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sem.h>
#include <sys/shm.h>
\&
#include "svshm_string.h"
\&
int
main(int argc, char *argv[])
{
    int            semid, shmid;
    char           *addr;
    size_t         len;
    struct sembuf  sop;
\&
    if (argc != 4) {
        fprintf(stderr, "Użycie: %s shmid semid łańcuch\[rs]n", argv[0]);
        exit(EXIT_FAILURE);
    }
\&
    len = strlen(argv[3]) + 1;  /* +1 aby objąć końcowe \[aq]\[rs]0\[aq] */
    if (len > MEM_SIZE) {
        fprintf(stderr, "Łańcuch jest zbyt długi!\[rs]n");
        exit(EXIT_FAILURE);
    }
\&
    /* Pobranie ID obiektów z wiersza polecenia. */
\&
    shmid = atoi(argv[1]);
    semid = atoi(argv[2]);
\&
    /* Dołączenie pamięci dzielonej do naszej przestrzeni adresowej
       i skopiowanie łańcucha (wraz z końcowym bajtem null) do pamięci. */
\&
    addr = shmat(shmid, NULL, 0);
    if (addr == (void *) \-1)
        errExit("shmat");
\&
    memcpy(addr, argv[3], len);
\&
    /* Zmniejszenie semafora do 0. */
\&
    sop.sem_num = 0;
    sop.sem_op = \-1;
    sop.sem_flg = 0;
\&
    if (semop(semid, &sop, 1) == \-1)
        errExit("semop");
\&
    exit(EXIT_SUCCESS);
}
.EE
.\" SRC END
.in
.SH "ZOBACZ TAKŻE"
\fBbrk\fP(2), \fBmmap\fP(2), \fBshmctl\fP(2), \fBshmget\fP(2), \fBcapabilities\fP(7),
\fBshm_overview\fP(7), \fBsysvipc\fP(7)
.PP
.SH TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika są:
Rafał Lewczuk <R.Lewczuk@elka.pw.edu.p>,
Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl>,
Robert Luberda <robert@debian.org>
i
Michał Kułach <michal.kulach@gmail.com>
.
.PP
Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach
licencji można uzyskać zapoznając się z
.UR https://www.gnu.org/licenses/gpl-3.0.html
GNU General Public License w wersji 3
.UE
lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.
.PP
Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy
dyskusyjnej
.MT manpages-pl-list@lists.sourceforge.net
.ME .
