SHMCTL(2)

NAZWA
shmctl - sterowanie segmentami pamięci dzielonej Systemu V

SKŁADNIA
#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

OPIS
shmctl() wykonuje operację określoną przez parametr cmd na segmencie pamięci dzielonej Systemu V o identyfikatorze shmid.

Parametr buf jest wskaźnikiem do struktury shmid_ds, zdefiniowanej następująco w <sys/shm.h>:

    struct shmid_ds {
        struct ipc_perm shm_perm;    /* Ownership and permissions */
        size_t          shm_segsz;   /* Size of segment (bytes) */
        time_t          shm_atime;   /* Last attach time */
        time_t          shm_dtime;   /* Last detach time */
        time_t          shm_ctime;   /* Creation time/time of last
                                        modification via shmctl() */
        pid_t           shm_cpid;    /* PID of creator */
        pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */
        shmatt_t        shm_nattch;  /* No. of current attaches */
        ...
    };

Pola struktury shmid_ds są następujące:

shm_perm
    This is an ipc_perm structure (see below) that specifies the access permissions on the shared memory segment.

shm_segsz
    Rozmiar segmentu pamięci wspólnej w bajtach.

shm_atime
    Time of the last shmat(2) system call that attached this segment.

shm_dtime
    Time of the last shmdt(2) system call that detached tgis segment.

shm_ctime
    Time of creation of segment or time of the last shmctl() IPC_SET operation.

shm_cpid
    Identyfikator procesu, który utworzył ten segment pamięci wspólnej.

shm_lpid
    ID of the last process that executed a shmat(2) or shmdt(2) system call on this segment.

shm_nattch
    Number of processes that have this segment attached.

Struktura ipc_perm jest zdefiniowana następująco (wyróżnione pola można ustawić za pomocą IPC_SET):

    struct ipc_perm {
        key_t          __key;    /* Klucz podany w msgget() */
        uid_t          uid;      /* Efektywny UID właściciela */
        gid_t          gid;      /* Efektywny GID właściciela */
        uid_t          cuid;     /* Efektywny UID twórcy */
        gid_t          cgid;     /* Efektywny GID twórcy */
        unsigned short mode;     /* Uprawnienia + znaczniki */
                                    SHM_DEST i SHM_LOCKED */
        unsigned short __seq;    /* Numer sekwencji */
    };

The least significant 9 bits of the mode field of the ipc_perm structure define the access permissions for the shared memory segment. The permission bits are as follows:
0400 | Read by user
0200 | Write by user
0040 | Read by group
0020 | Write by group
0004 | Read by others
0002 | Write by others

Bits 0100, 0010, and 0001 (the execute bits) are unused by the system. (It is not necessary to have execute permission on a segment in order to perform a shmat(2) call with the SHM_EXEC flag.)

Poprawne wartości parametru cmd to:

IPC_STAT
    Kopiuje informacje ze struktury kontrolnej jądra skojarzonej z shmid do struktury wskazywanej przez buf. Wywołujący musi mieć uprawnienie odczytu segmentu pamięci dzielonej.

IPC_SET
    Write the values of some members of the shmid_ds structure pointed to by buf to the kernel data structure associated with this shared memory segment, updating also its shm_ctime member.

    The following fields are updated: shm_perm.uid, shm_perm.gid, and (the least significant 9 bits of) shm_perm.mode.

    The effective UID of the calling process must match the owner (shm_perm.uid) or creator (shm_perm.cuid) of the shared memory segment, or the caller must be privileged.

IPC_RMID
    Zaznacza segment do usunięcia. Zostanie on naprawdę usunięty jedynie w momencie, w którym ostatni używający go proces się od niego odłączy (tj. gdy pole shm_nattch struktury shmid_ds opisującej segment osiągnie wartość zero). Użytkownik musi być właścicielem segmentu, jego twórcą lub użytkownikiem uprzywilejowanym. Argument buf jest ignorowany.

    Jeśli segment został zaznaczony do usunięcia, to zostanie ustawiony (niestandardowy) znacznik SHM_DEST pola shm_perm.mode struktury danych zwracanej przez IPC_STAT.

    Wywołujący musi zapewnić, że segment po użyciu zostanie na pewno usunięty. W przeciwnym przypadku pamięć lub obszar wymiany zajmowane przez segment nie zostaną zwolnione.

    Proszę zapoznać się również z opisem z /proc/sys/kernel/shm_rmid_forced w proc(5).

IPC_INFO (specyficzne dla Linuksa)
    Zwraca w strukturze, na którą wskazuje buf, informacje o systemowych ograniczeniach i parametrach pamięci dzielonej. Struktura jest typu shminfo (dlatego wymagane jest rzutowanie) i jest zdefiniowana w <sys/shm.h>, pod warunkiem, że zdefiniowano również makro _GNU_SOURCE:

        struct shminfo {
            unsigned long shmmax; /* Maksymalny rozmiar segmentu */
            unsigned long shmmin; /* Minimalny rozmiar segmentu;
                                     zawsze 1 */
            unsigned long shmmni; /* Maksymalna liczba segmentów */
            unsigned long shmseg; /* Maksymalna liczba segmentów,
                                     które proces może podłączyć;
                                     nieużywane przez jądro */
            unsigned long shmall; /* Maksymalna liczba stron
                                     pamięci dzielonej, globalna
                                     dla systemu */
        };

    Ustawienia shmmni, shmmax oraz shmall można zmienić za pomocą plików /proc o nazwach takich samych, jak nazwy tych ustawień; szczegóły można znaleźć w podręczniku proc(5).

SHM_INFO (specyficzne dla Linuksa)
    Zwraca strukturę shm_info, której pola zawierają informacje o zasobach systemowych używanych przez pamięć dzieloną. Struktura jest zdefiniowana w <sys/shm.h>, pod warunkiem, że zdefiniowano również makro _GNU_SOURCE:

        struct shm_info {
            int           used_ids; /* Liczba istniejących
                                       obecnie segmentów */
            unsigned long shm_tot;  /* Całkowita liczba stron
                                       pamięci dzielonej */
            unsigned long shm_rss;  /* Liczba stron pamięci dzielonej
                                       w fizycznej pamięci */
            unsigned long shm_swp;  /* Liczba stron pamięci dzielonej
                                       w przestrzeni wymiany */
            unsigned long swap_attempts;
                                    /* Nieużywane od Linuksa 2.4 */
            unsigned long swap_successes;
                                    /* Nieużywane od Linuksa 2.4 */
        };

SHM_STAT (specyficzne dla Linuksa)
    Zwraca strukturę shmid_ds, taką jak dla IPC_STAT. Jednakże parametr shmid nie jest identyfikatorem segmentu, ale indeksem wewnętrznej tablicy jądra przechowującej informacje o wszystkich segmentach pamięci dzielonej w systemie.

SHM_STAT_ANY (Linux-specific, since Linux 4.17)
    Return a shmid_ds structure as for SHM_STAT. However, shm_perm.mode is not checked for read access for shmid, meaning that any user can employ this operation (just as any user may read /proc/sysvipc/shm to obtain the same information).

Proces wywołujący może zabronić lub zezwolić na wymianę obszarów pamięci zajmowanych przez segment, używając następujących wartości cmd:

SHM_LOCK (specyficzne dla Linuksa)
    Zapobiega umieszczaniu segmentu pamięci dzielonej w przestrzeni wymiany. The caller must fault in any pages that are required to be present after locking is enabled. Jeśli segment jest zablokowany, to zostanie ustawiony (niestandardowy) znacznik SHM_LOCKED pola shm_perm.mode struktury danych zwracanej przez IPC_STAT.

SHM_UNLOCK (specyficzne dla Linuksa)
    Odblokowuje segment, zezwalając na umieszczenie go w przestrzeni wymiany.

W jądrach wcześniejszych niż 2.6.10 tylko proces uprzywilejowany mógł stosować SHM_LOCK i SHM_UNLOCK. Od jądra 2.6.10 nieuprzywilejowany proces może wywołać te operacje, pod warunkiem że efektywny identyfikator użytkownika odpowiada identyfikatorowi twórcy lub właściciela segmentu oraz (w przypadku SHM_LOCK) ilość pamięci do zablokowania mieści się w ograniczeniu zasobów RLIMIT_MEMLOCK (patrz setrlimit(2)).

WARTOŚĆ ZWRACANA
Pomyślnie zakończone operacje IPC_INFO i SHM_INFO zwracają indeks najwyższego używanego wpisu w wewnętrznej tablicy jądra przechowującej informacje o wszystkich segmentach pamięci dzielonej. (Informacji tej można użyć w operacjach SHM_STAT lub SHM_STAT_ANY, aby otrzymać informacje o wszystkich segmentach pamięci dzielonej w systemie). Pomyślnie zakończona operacja SHM_STAT zwraca identyfikator segmentu pamięci dzielonej o indeksie przekazanym w shmid. Pozostałe operacje zwracają 0, jeżeli tylko się powiodą.

W razie wystąpienia błędu zwracane jest -1 i ustawiana jest odpowiednia wartość zmiennej errno.

BŁĘDY

EACCES
    IPC_STAT or SHM_STAT is requested and shm_perm.mode does not allow read access for shmid, and the calling process does not have the CAP_IPC_OWNER capability in the user namespace that governs its IPC namespace.

EFAULT
    Parametr cmd ma wartość IPC_SET lub IPC_STAT, ale adres wskazany przez buf jest niedostępny.

EIDRM
    shmid wskazuje na usunięty identyfikator.

EINVAL
    shmid nie jest poprawnym identyfikatorem lub cmd nie jest poprawnym poleceniem. Albo: w przypadku operacji SHM_STAT lub SHM_STAT_ANY wartość indeksu podana w parametrze shmid odwoływała się do obecnie nieużywanego elementu tablicy.

ENOMEM
    (W jądrach wcześniejszych niż 2.6.9) podano SHM_LOCK, a rozmiar segmentu do zablokowania oznaczałby przekroczenie ograniczenia na całkowitą liczbę bajtów w pamięci dzielonej przypadającą na rzeczywisty identyfikator użytkownika procesu wywołującego. Ograniczenie to jest opisywane przez miękki limit zasobu RLIMIT_MEMLOCK (patrz setrlimit(2)).

EOVERFLOW
    Próbowano wywołać polecenie IPC_STAT, a wartość GID lub UID jest za duża, aby ją umieścić w strukturze wskazywanej przez buf.

EPERM
    Próbowano wywołać polecenie IPC_SET lub IPC_RMID, ale efektywny UID właściciela wywołującego procesu nie odpowiada twórcy segmentu (określonemu w shm_perm.cuid), właścicielowi segmentu (określonemu w shm_perm.uid), a proces nie jest uprzywilejowany (Linux: nie ma ustawionego atrybutu CAP_SYS_ADMIN).

    Lub (w jądrach starszych niż 2.6.9) podano SHM_LOCK lub SHM_UNLOCK, ale proces nie był uprzywilejowany (Linux: nie miał ustawionego atrybutu CAP_IPC_LOCK). (Od wersji Linuksa 2.6.9 ten błąd może wystąpić również gdy RLIMIT_MEMLOCK jest równy 0 i proces wywołujący nie jest uprzywilejowany).

ZGODNE Z
POSIX.1-2001, POSIX.1-2008, SVr4.

UWAGI
Dołączenie <sys/types.h> i <sys/ipc.h> nie jest wymagane na Linuksie ani przez żadną z wersji POSIX. Jednak niektóre stare implementacje wymagają dołączenia tych plików nagłówkowych, SVID również dokumentuje ich dołączenie. Aplikacje które mają być przenośne na tego typu stare systemy mogą wymagać dołączenia omawianych plików nagłówkowych.

Operacje IPC_INFO, SHM_STAT oraz SHM_INFO są używane przez program ipcs(1) w celu dostarczenia informacji o zajmowanych zasobach. W przyszłości operacje te mogą zostać zmodyfikowane lub przeniesione do interfejsu systemu plików /proc.

Linux pozwala na dołączenie (shmat(2)) segmentu pamięci dzielonej, który już został zaznaczony do usunięcia za pomocą shmctl(IPC_RMID). Ta właściwość nie jest dostępna w innych implementacjach Uniksa; przenośne aplikacje nie powinny od niej zależeć.

Niektóre pola struktury struct shmid_ds były w Linuksie 2.2 typu short, ale stały się typu long w Linuksie 2.4. Aby to wykorzystać, powinna wystarczyć rekompilacja pod glibc-2.1.91 lub nowszą. (Jądro rozróżnia stare wywołania od nowych za pomocą znacznika IPC_64 w cmd).

ZOBACZ TAKŻE
mlock(2), setrlimit(2), shmget(2), shmop(2), capabilities(7), sysvipc(7)

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

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> 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 manpages-pl-list@lists.sourceforge.net.