1SHMOP(2)                   Linux Programmer's Manual                  SHMOP(2)
2
3
4

NAME

6       shmat, shmdt - System V shared memory operations
7

SYNOPSIS

9       #include <sys/shm.h>
10
11       void *shmat(int shmid, const void *shmaddr, int shmflg);
12       int shmdt(const void *shmaddr);
13

DESCRIPTION

15   shmat()
16       shmat() attaches the System V shared memory segment identified by shmid
17       to the address space of the calling process.  The attaching address  is
18       specified by shmaddr with one of the following criteria:
19
20       • If  shmaddr  is  NULL,  the  system chooses a suitable (unused) page-
21         aligned address to attach the segment.
22
23       • If shmaddr isn't NULL and SHM_RND is specified in shmflg, the  attach
24         occurs  at  the  address equal to shmaddr rounded down to the nearest
25         multiple of SHMLBA.
26
27       • Otherwise, shmaddr must be a page-aligned address at which the attach
28         occurs.
29
30       In  addition  to  SHM_RND,  the following flags may be specified in the
31       shmflg bit-mask argument:
32
33       SHM_EXEC (Linux-specific; since Linux 2.6.9)
34              Allow the contents of the segment to be  executed.   The  caller
35              must have execute permission on the segment.
36
37       SHM_RDONLY
38              Attach  the segment for read-only access.  The process must have
39              read permission for the segment.  If this flag is not specified,
40              the  segment  is  attached  for  read  and write access, and the
41              process must have read and write  permission  for  the  segment.
42              There is no notion of a write-only shared memory segment.
43
44       SHM_REMAP (Linux-specific)
45              This  flag  specifies that the mapping of the segment should re‐
46              place any existing mapping in the range starting at shmaddr  and
47              continuing  for  the  size of the segment.  (Normally, an EINVAL
48              error would result if a mapping already exists in  this  address
49              range.)  In this case, shmaddr must not be NULL.
50
51       The  brk(2)  value of the calling process is not altered by the attach.
52       The segment will automatically be detached at process exit.   The  same
53       segment  may  be  attached  as a read and as a read-write one, and more
54       than once, in the process's address space.
55
56       A successful shmat() call updates the members of the shmid_ds structure
57       (see shmctl(2)) associated with the shared memory segment as follows:
58
59shm_atime is set to the current time.
60
61shm_lpid is set to the process-ID of the calling process.
62
63shm_nattch is incremented by one.
64
65   shmdt()
66       shmdt() detaches the shared memory segment located at the address spec‐
67       ified by shmaddr from the address space of the  calling  process.   The
68       to-be-detached segment must be currently attached with shmaddr equal to
69       the value returned by the attaching shmat() call.
70
71       On a successful shmdt() call, the system updates  the  members  of  the
72       shmid_ds  structure  associated  with the shared memory segment as fol‐
73       lows:
74
75shm_dtime is set to the current time.
76
77shm_lpid is set to the process-ID of the calling process.
78
79shm_nattch is decremented by one.  If it becomes 0 and the segment is
80         marked for deletion, the segment is deleted.
81

RETURN VALUE

83       On  success,  shmat() returns the address of the attached shared memory
84       segment; on error, (void *) -1 is returned, and errno is set  to  indi‐
85       cate the error.
86
87       On  success,  shmdt()  returns 0; on error -1 is returned, and errno is
88       set to indicate the error.
89

ERRORS

91       shmat() can fail with one of the following errors:
92
93       EACCES The calling process does not have the required  permissions  for
94              the  requested  attach type, and does not have the CAP_IPC_OWNER
95              capability in the user namespace that governs its IPC namespace.
96
97       EIDRM  shmid points to a removed identifier.
98
99       EINVAL Invalid shmid  value,  unaligned  (i.e.,  not  page-aligned  and
100              SHM_RND  was  not  specified) or invalid shmaddr value, or can't
101              attach segment  at  shmaddr,  or  SHM_REMAP  was  specified  and
102              shmaddr was NULL.
103
104       ENOMEM Could not allocate memory for the descriptor or for the page ta‐
105              bles.
106
107       shmdt() errno can fail with one of the following errors:
108
109       EINVAL There is no shared  memory  segment  attached  at  shmaddr;  or,
110              shmaddr is not aligned on a page boundary.
111

CONFORMING TO

113       POSIX.1-2001, POSIX.1-2008, SVr4.
114
115       In  SVID  3  (or perhaps earlier), the type of the shmaddr argument was
116       changed from char * into const void *, and the returned type of shmat()
117       from char * into void *.
118

NOTES

120       After  a  fork(2),  the  child inherits the attached shared memory seg‐
121       ments.
122
123       After an execve(2), all attached shared memory  segments  are  detached
124       from the process.
125
126       Upon  _exit(2),  all  attached shared memory segments are detached from
127       the process.
128
129       Using shmat() with shmaddr equal to NULL is the preferred, portable way
130       of  attaching a shared memory segment.  Be aware that the shared memory
131       segment attached in this way may be attached at different addresses  in
132       different  processes.   Therefore,  any  pointers maintained within the
133       shared memory must be made relative (typically to the starting  address
134       of the segment), rather than absolute.
135
136       On  Linux,  it is possible to attach a shared memory segment even if it
137       is already marked to be deleted.  However,  POSIX.1  does  not  specify
138       this behavior and many other implementations do not support it.
139
140       The following system parameter affects shmat():
141
142       SHMLBA Segment low boundary address multiple.  When explicitly specify‐
143              ing an attach address in a call to shmat(),  the  caller  should
144              ensure  that  the  address is a multiple of this value.  This is
145              necessary on some architectures, in order either to ensure  good
146              CPU  cache  performance  or to ensure that different attaches of
147              the same segment have consistent views  within  the  CPU  cache.
148              SHMLBA  is  normally some multiple of the system page size.  (On
149              many Linux architectures, SHMLBA is the same as the system  page
150              size.)
151
152       The  implementation places no intrinsic per-process limit on the number
153       of shared memory segments (SHMSEG).
154

EXAMPLES

156       The two programs shown below exchange a string using  a  shared  memory
157       segment.   Further  details about the programs are given below.  First,
158       we show a shell session demonstrating their use.
159
160       In one terminal window, we run the "reader" program,  which  creates  a
161       System  V shared memory segment and a System V semaphore set.  The pro‐
162       gram prints out the IDs of the created objects, and then waits for  the
163       semaphore to change value.
164
165           $ ./svshm_string_read
166           shmid = 1114194; semid = 15
167
168       In  another terminal window, we run the "writer" program.  The "writer"
169       program takes three command-line arguments: the IDs of the shared  mem‐
170       ory  segment  and  semaphore set created by the "reader", and a string.
171       It attaches the existing shared memory segment, copies  the  string  to
172       the shared memory, and modifies the semaphore value.
173
174           $ ./svshm_string_write 1114194 15 'Hello, world'
175
176       Returning  to  the  terminal where the "reader" is running, we see that
177       the program has ceased waiting on the semaphore  and  has  printed  the
178       string that was copied into the shared memory segment by the writer:
179
180           Hello, world
181
182   Program source: svshm_string.h
183       The following header file is included by the "reader" and "writer" pro‐
184       grams.
185
186           #include <sys/types.h>
187           #include <sys/ipc.h>
188           #include <sys/shm.h>
189           #include <sys/sem.h>
190           #include <stdio.h>
191           #include <stdlib.h>
192           #include <string.h>
193
194           #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
195                                   } while (0)
196
197           union semun {                   /* Used in calls to semctl() */
198               int                 val;
199               struct semid_ds *   buf;
200               unsigned short *    array;
201           #if defined(__linux__)
202               struct seminfo *    __buf;
203           #endif
204           };
205
206           #define MEM_SIZE 4096
207
208   Program source: svshm_string_read.c
209       The "reader" program creates a shared memory segment  and  a  semaphore
210       set  containing  one semaphore.  It then attaches the shared memory ob‐
211       ject into its address space and initializes the semaphore value  to  1.
212       Finally, the program waits for the semaphore value to become 0, and af‐
213       terwards prints the string that has been copied into the shared  memory
214       segment by the "writer".
215
216           /* svshm_string_read.c
217
218              Licensed under GNU General Public License v2 or later.
219           */
220           #include "svshm_string.h"
221
222           int
223           main(int argc, char *argv[])
224           {
225               int semid, shmid;
226               union semun arg, dummy;
227               struct sembuf sop;
228               char *addr;
229
230               /* Create shared memory and semaphore set containing one
231                  semaphore. */
232
233               shmid = shmget(IPC_PRIVATE, MEM_SIZE, IPC_CREAT | 0600);
234               if (shmid == -1)
235                   errExit("shmget");
236
237               semid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
238               if (semid == -1)
239                   errExit("semget");
240
241               /* Attach shared memory into our address space. */
242
243               addr = shmat(shmid, NULL, SHM_RDONLY);
244               if (addr == (void *) -1)
245                   errExit("shmat");
246
247               /* Initialize semaphore 0 in set with value 1. */
248
249               arg.val = 1;
250               if (semctl(semid, 0, SETVAL, arg) == -1)
251                   errExit("semctl");
252
253               printf("shmid = %d; semid = %d\n", shmid, semid);
254
255               /* Wait for semaphore value to become 0. */
256
257               sop.sem_num = 0;
258               sop.sem_op = 0;
259               sop.sem_flg = 0;
260
261               if (semop(semid, &sop, 1) == -1)
262                   errExit("semop");
263
264               /* Print the string from shared memory. */
265
266               printf("%s\n", addr);
267
268               /* Remove shared memory and semaphore set. */
269
270               if (shmctl(shmid, IPC_RMID, NULL) == -1)
271                   errExit("shmctl");
272               if (semctl(semid, 0, IPC_RMID, dummy) == -1)
273                   errExit("semctl");
274
275               exit(EXIT_SUCCESS);
276           }
277
278   Program source: svshm_string_write.c
279       The  writer  program takes three command-line arguments: the IDs of the
280       shared memory segment and semaphore set that have already been  created
281       by  the  "reader", and a string.  It attaches the shared memory segment
282       into its address space, and then decrements the semaphore value to 0 in
283       order  to  inform  the "reader" that it can now examine the contents of
284       the shared memory.
285
286           /* svshm_string_write.c
287
288              Licensed under GNU General Public License v2 or later.
289           */
290           #include "svshm_string.h"
291
292           int
293           main(int argc, char *argv[])
294           {
295               int semid, shmid;
296               struct sembuf sop;
297               char *addr;
298               size_t len;
299
300               if (argc != 4) {
301                   fprintf(stderr, "Usage: %s shmid semid string\n", argv[0]);
302                   exit(EXIT_FAILURE);
303               }
304
305               len = strlen(argv[3]) + 1;  /* +1 to include trailing '\0' */
306               if (len > MEM_SIZE) {
307                   fprintf(stderr, "String is too big!\n");
308                   exit(EXIT_FAILURE);
309               }
310
311               /* Get object IDs from command-line. */
312
313               shmid = atoi(argv[1]);
314               semid = atoi(argv[2]);
315
316               /* Attach shared memory into our address space and copy string
317                  (including trailing null byte) into memory. */
318
319               addr = shmat(shmid, NULL, 0);
320               if (addr == (void *) -1)
321                   errExit("shmat");
322
323               memcpy(addr, argv[3], len);
324
325               /* Decrement semaphore to 0. */
326
327               sop.sem_num = 0;
328               sop.sem_op = -1;
329               sop.sem_flg = 0;
330
331               if (semop(semid, &sop, 1) == -1)
332                   errExit("semop");
333
334               exit(EXIT_SUCCESS);
335           }
336

SEE ALSO

338       brk(2),  mmap(2),  shmctl(2),  shmget(2),  capabilities(7),   shm_over‐
339       view(7), sysvipc(7)
340

COLOPHON

342       This  page  is  part of release 5.12 of the Linux man-pages project.  A
343       description of the project, information about reporting bugs,  and  the
344       latest     version     of     this    page,    can    be    found    at
345       https://www.kernel.org/doc/man-pages/.
346
347
348
349Linux                             2021-03-22                          SHMOP(2)
Impressum