diff options
Diffstat (limited to '')
-rw-r--r-- | man2/shmop.2 | 507 |
1 files changed, 507 insertions, 0 deletions
diff --git a/man2/shmop.2 b/man2/shmop.2 new file mode 100644 index 0000000..09168ec --- /dev/null +++ b/man2/shmop.2 @@ -0,0 +1,507 @@ +.\" 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 +.\" +.TH SHMOP 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +shmat, shmdt \- System V shared memory operations +.SH LIBRARY +Standard C library +.RI ( libc ", " \-lc ) +.SH SYNOPSIS +.nf +.B #include <sys/shm.h> +.PP +.BI "void *shmat(int " shmid ", const void *_Nullable " shmaddr ", \ +int " shmflg ); +.BI "int shmdt(const void *" shmaddr ); +.fi +.SH DESCRIPTION +.SS shmat() +.BR shmat () +attaches the System\ V shared memory segment identified by +.I shmid +to the address space of the calling process. +The attaching address is specified by +.I shmaddr +with one of the following criteria: +.IP \[bu] 3 +If +.I shmaddr +is NULL, +the system chooses a suitable (unused) page-aligned address to attach +the segment. +.IP \[bu] +If +.I shmaddr +isn't NULL +and +.B SHM_RND +is specified in +.IR shmflg , +the attach occurs at the address equal to +.I shmaddr +rounded down to the nearest multiple of +.BR SHMLBA . +.IP \[bu] +Otherwise, +.I shmaddr +must be a page-aligned address at which the attach occurs. +.PP +In addition to +.BR SHM_RND , +the following flags may be specified in the +.I shmflg +bit-mask argument: +.TP +.BR SHM_EXEC " (Linux-specific; since Linux 2.6.9)" +Allow the contents of the segment to be executed. +The caller must have execute permission on the segment. +.TP +.B SHM_RDONLY +Attach the segment for read-only access. +The process must have read permission for the segment. +If this flag is not specified, +the segment is attached for read and write access, +and the process must have read and write permission for the segment. +There is no notion of a write-only shared memory segment. +.TP +.BR SHM_REMAP " (Linux-specific)" +This flag specifies +that the mapping of the segment should replace +any existing mapping in the range starting at +.I shmaddr +and continuing for the size of the segment. +(Normally, an +.B EINVAL +error would result if a mapping already exists in this address range.) +In this case, +.I shmaddr +must not be NULL. +.PP +The +.BR brk (2) +value of the calling process is not altered by the attach. +The segment will automatically be detached at process exit. +The same segment may be attached as a read and as a read-write +one, and more than once, in the process's address space. +.PP +A successful +.BR shmat () +call updates the members of the +.I shmid_ds +structure (see +.BR shmctl (2)) +associated with the shared memory segment as follows: +.IP \[bu] 3 +.I shm_atime +is set to the current time. +.IP \[bu] +.I shm_lpid +is set to the process-ID of the calling process. +.IP \[bu] +.I shm_nattch +is incremented by one. +.\" +.SS shmdt() +.BR shmdt () +detaches the shared memory segment located at the address specified by +.I shmaddr +from the address space of the calling process. +The to-be-detached segment must be currently +attached with +.I shmaddr +equal to the value returned by the attaching +.BR shmat () +call. +.PP +On a successful +.BR shmdt () +call, the system updates the members of the +.I shmid_ds +structure associated with the shared memory segment as follows: +.IP \[bu] 3 +.I shm_dtime +is set to the current time. +.IP \[bu] +.I shm_lpid +is set to the process-ID of the calling process. +.IP \[bu] +.I shm_nattch +is decremented by one. +If it becomes 0 and the segment is marked for deletion, +the segment is deleted. +.SH RETURN VALUE +On success, +.BR shmat () +returns the address of the attached shared memory segment; on error, +.I (void\ *)\ \-1 +is returned, and +.I errno +is set to indicate the error. +.PP +On success, +.BR shmdt () +returns 0; on error \-1 is returned, and +.I errno +is set to indicate the error. +.SH ERRORS +.BR shmat () +can fail with one of the following errors: +.TP +.B EACCES +The calling process does not have the required permissions for +the requested attach type, and does not have the +.B CAP_IPC_OWNER +capability in the user namespace that governs its IPC namespace. +.TP +.B EIDRM +\fIshmid\fP points to a removed identifier. +.TP +.B EINVAL +Invalid +.I shmid +value, unaligned (i.e., not page-aligned and \fBSHM_RND\fP was not +specified) or invalid +.I shmaddr +value, or can't attach segment at +.IR shmaddr , +or +.B SHM_REMAP +was specified and +.I shmaddr +was NULL. +.TP +.B ENOMEM +Could not allocate memory for the descriptor or for the page tables. +.PP +.BR shmdt () +can fail with one of the following errors: +.TP +.B EINVAL +There is no shared memory segment attached at +.IR shmaddr ; +or, +.\" The following since Linux 2.6.17-rc1: +.I shmaddr +is not aligned on a page boundary. +.SH STANDARDS +POSIX.1-2008. +.SH HISTORY +POSIX.1-2001, SVr4. +.\" SVr4 documents an additional error condition EMFILE. +.PP +In SVID 3 (or perhaps earlier), +the type of the \fIshmaddr\fP argument was changed from +.I "char\ *" +into +.IR "const void\ *" , +and the returned type of +.BR shmat () +from +.I "char\ *" +into +.IR "void\ *" . +.SH NOTES +After a +.BR fork (2), +the child inherits the attached shared memory segments. +.PP +After an +.BR execve (2), +all attached shared memory segments are detached from the process. +.PP +Upon +.BR _exit (2), +all attached shared memory segments are detached from the process. +.PP +Using +.BR shmat () +with +.I shmaddr +equal to NULL +is the preferred, portable way of attaching a shared memory segment. +Be aware that the shared memory segment attached in this way +may be attached at different addresses in different processes. +Therefore, any pointers maintained within the shared memory must be +made relative (typically to the starting address of the segment), +rather than absolute. +.PP +On Linux, it is possible to attach a shared memory segment even if it +is already marked to be deleted. +However, POSIX.1 does not specify this behavior and +many other implementations do not support it. +.PP +The following system parameter affects +.BR shmat (): +.TP +.B SHMLBA +Segment low boundary address multiple. +When explicitly specifying an attach address in a call to +.BR shmat (), +the caller should ensure that the address is a multiple of this value. +This is necessary on some architectures, +in order either to ensure good CPU cache performance or to ensure that +different attaches of the same segment have consistent views +within the CPU cache. +.B SHMLBA +is normally some multiple of the system page size. +(On many Linux architectures, +.B SHMLBA +is the same as the system page size.) +.PP +The implementation places no intrinsic per-process limit on the +number of shared memory segments +.RB ( SHMSEG ). +.SH EXAMPLES +The two programs shown below exchange a string using a shared memory segment. +Further details about the programs are given below. +First, we show a shell session demonstrating their use. +.PP +In one terminal window, we run the "reader" program, +which creates a System V shared memory segment and a System V semaphore set. +The program prints out the IDs of the created objects, +and then waits for the semaphore to change value. +.PP +.in +4n +.EX +$ \fB./svshm_string_read\fP +shmid = 1114194; semid = 15 +.EE +.in +.PP +In another terminal window, we run the "writer" program. +The "writer" program takes three command-line arguments: +the IDs of the shared memory segment and semaphore set created +by the "reader", and a string. +It attaches the existing shared memory segment, +copies the string to the shared memory, and modifies the semaphore value. +.PP +.in +4n +.EX +$ \fB./svshm_string_write 1114194 15 \[aq]Hello, world\[aq]\fP +.EE +.in +.PP +Returning to the terminal where the "reader" is running, +we see that the program has ceased waiting on the semaphore +and has printed the string that was copied into the +shared memory segment by the writer: +.PP +.in +4n +.EX +Hello, world +.EE +.in +.\" +.SS Program source: svshm_string.h +The following header file is included by the "reader" and "writer" programs: +.PP +.in +4n +.\" SRC BEGIN (svshm_string.h) +.EX +/* svshm_string.h +\& + Licensed under GNU General Public License v2 or later. +*/ +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/sem.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +\& +#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e + } while (0) +\& +union semun { /* Used in calls to semctl() */ + int val; + struct semid_ds * buf; + unsigned short * array; +#if defined(__linux__) + struct seminfo * __buf; +#endif +}; +\& +#define MEM_SIZE 4096 +.EE +.\" SRC END +.in +.\" +.SS Program source: svshm_string_read.c +The "reader" program creates a shared memory segment and a semaphore set +containing one semaphore. +It then attaches the shared memory object into its address space +and initializes the semaphore value to 1. +Finally, the program waits for the semaphore value to become 0, +and afterwards prints the string that has been copied into the +shared memory segment by the "writer". +.PP +.in +4n +.\" SRC BEGIN (svshm_string_read.c) +.EX +/* svshm_string_read.c +\& + Licensed under GNU General Public License v2 or later. +*/ +#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; +\& + /* Create shared memory and semaphore set containing one + semaphore. */ +\& + 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"); +\& + /* Attach shared memory into our address space. */ +\& + addr = shmat(shmid, NULL, SHM_RDONLY); + if (addr == (void *) \-1) + errExit("shmat"); +\& + /* Initialize semaphore 0 in set with value 1. */ +\& + arg.val = 1; + if (semctl(semid, 0, SETVAL, arg) == \-1) + errExit("semctl"); +\& + printf("shmid = %d; semid = %d\en", shmid, semid); +\& + /* Wait for semaphore value to become 0. */ +\& + sop.sem_num = 0; + sop.sem_op = 0; + sop.sem_flg = 0; +\& + if (semop(semid, &sop, 1) == \-1) + errExit("semop"); +\& + /* Print the string from shared memory. */ +\& + printf("%s\en", addr); +\& + /* Remove shared memory and semaphore set. */ +\& + 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 Program source: svshm_string_write.c +The writer program takes three command-line arguments: +the IDs of the shared memory segment and semaphore set +that have already been created by the "reader", and a string. +It attaches the shared memory segment into its address space, +and then decrements the semaphore value to 0 in order to inform the +"reader" that it can now examine the contents of the shared memory. +.PP +.in +4n +.\" SRC BEGIN (svshm_string_write.c) +.EX +/* svshm_string_write.c +\& + Licensed under GNU General Public License v2 or later. +*/ +#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, "Usage: %s shmid semid string\en", argv[0]); + exit(EXIT_FAILURE); + } +\& + len = strlen(argv[3]) + 1; /* +1 to include trailing \[aq]\e0\[aq] */ + if (len > MEM_SIZE) { + fprintf(stderr, "String is too big!\en"); + exit(EXIT_FAILURE); + } +\& + /* Get object IDs from command\-line. */ +\& + shmid = atoi(argv[1]); + semid = atoi(argv[2]); +\& + /* Attach shared memory into our address space and copy string + (including trailing null byte) into memory. */ +\& + addr = shmat(shmid, NULL, 0); + if (addr == (void *) \-1) + errExit("shmat"); +\& + memcpy(addr, argv[3], len); +\& + /* Decrement semaphore to 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 SEE ALSO +.BR brk (2), +.BR mmap (2), +.BR shmctl (2), +.BR shmget (2), +.BR capabilities (7), +.BR shm_overview (7), +.BR sysvipc (7) |