aboutsummaryrefslogtreecommitdiffstats
path: root/man3
diff options
context:
space:
mode:
authorMichael Kerrisk <mtk.manpages@gmail.com>2020-02-28 16:07:24 +0100
committerMichael Kerrisk <mtk.manpages@gmail.com>2020-03-12 09:24:44 +0100
commit145b262dda5c57b57ab112d3f656cdef6bb06816 (patch)
tree8b2b6148e61f2d8a96e90be3befa90ef6df77c9c /man3
parente5d8f6046b7b675f4ed4a97ff4e84a3d3b02edae (diff)
downloadman-pages-145b262dda5c57b57ab112d3f656cdef6bb06816.tar.gz
shm_open.3: EXAMPLE: add some example programs
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
Diffstat (limited to 'man3')
-rw-r--r--man3/shm_open.3218
1 files changed, 216 insertions, 2 deletions
diff --git a/man3/shm_open.3 b/man3/shm_open.3
index 39ca9e2617..675d44df96 100644
--- a/man3/shm_open.3
+++ b/man3/shm_open.3
@@ -1,4 +1,4 @@
-.\" Copyright (C) 2002 Michael Kerrisk <mtk.manpages@gmail.com>
+.\" Copyright (C) 2002, 2020 Michael Kerrisk <mtk.manpages@gmail.com>
.\"
.\" %%%LICENSE_START(VERBATIM)
.\" Permission is granted to make and distribute verbatim copies of this
@@ -22,7 +22,6 @@
.\" the source, must acknowledge the copyright and authors of this work.
.\" %%%LICENSE_END
.\"
-.\" FIXME . Add an example to this page
.TH SHM_OPEN 3 2017-09-15 "Linux" "Linux Programmer's Manual"
.SH NAME
shm_open, shm_unlink \- create/open or unlink POSIX shared memory objects
@@ -286,6 +285,221 @@ of a dedicated
.BR tmpfs (5)
filesystem that is normally mounted under
.IR /dev/shm .
+.SH EXAMPLE
+The programs below employ POSIX shared memory and POSIX unnamed semaphores
+to exchange a piece of data.
+The "bounce" program (which must be run first) raises the case
+of a string that is placed into the shared memory by the "send" program.
+Once the data has been modified, the "send" program then prints
+the contents of the modified shared memory.
+An example execution of the two programs is the following:
+.PP
+.in +4n
+.EX
+$ \fB./pshm_ucase_bounce /myshm &\fP
+[1] 270171
+$ \fB./pshm_ucase_send /myshm hello\fP
+HELLO
+.EE
+.in
+.PP
+Further detail about these programs is provided below.
+.\"
+.SS Program source: pshm_ucase.h
+The following header file is included by both programs below.
+Its primary purpose is to define a structure that will be imposed
+on the memory object that is shared between the two programs.
+.PP
+.in +4n
+.EX
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
+ } while (0)
+
+#define BUF_SIZE 1024 /* Maximum size for exchanged string */
+
+/* Define a structure that will be imposed on the shared
+ memory object */
+
+struct shmbuf {
+ sem_t sem1; /* POSIX unnamed semaphore */
+ sem_t sem2; /* POSIX unnamed semaphore */
+ size_t cnt; /* Number of bytes used in \(aqbuf\(aq */
+ char buf[BUF_SIZE]; /* Data being transferred */
+};
+.EE
+.in
+.PP
+.\"
+.SS Program source: pshm_ucase_bounce.c
+.PP
+The "bounce" program creates a new shared memory object with the name
+given in its command-line argument and sizes the object to
+match the size of the
+.I shmbuf
+structure defined in the header file.
+It then maps the object into the process's address space,
+and initializes two POSIX semaphores inside the object to 0.
+.PP
+After the "send" program has posted the first of the semaphores,
+the "bounce" program upper cases the data that has been placed
+in the memory by the "send" program and then posts the second semaphore
+to tell the "send" program that it may now access the shared memory.
+.PP
+.in +4n
+.EX
+#include <ctype.h>
+#include "pshm_ucase.h"
+
+int
+main(int argc, char *argv[])
+{
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s /shm\-path\en", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ char *shmpath = argv[1];
+
+ /* Create shared memory object and set its size to the size
+ of our structure */
+
+ int fd = shm_open(shmpath, O_CREAT | O_EXCL | O_RDWR,
+ S_IRUSR | S_IWUSR);
+ if (fd == \-1)
+ errExit("shm_open");
+
+ if (ftruncate(fd, sizeof(struct shmbuf)) == \-1)
+ errExit("ftruncate");
+
+ /* Map the object into the caller\(aqs address space */
+
+ struct shmbuf *shmp = mmap(NULL, sizeof(struct shmbuf),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (shmp == MAP_FAILED)
+ errExit("mmap");
+
+ /* Initialize semaphores as process-shared, with value 0 */
+
+ if (sem_init(&shmp\->sem1, 1, 0) == \-1)
+ errExit("sem_init\-sem1");
+ if (sem_init(&shmp\->sem2, 1, 0) == \-1)
+ errExit("sem_init\-sem2");
+
+ /* Wait for \(aqsem1\(aq to be posted by peer before touching
+ shared memory */
+
+ if (sem_wait(&shmp\->sem1) == \-1)
+ errExit("sem_wait");
+
+ /* Convert data in shared memory into upper case */
+
+ for (int j = 0; j < shmp\->cnt; j++)
+ shmp\->buf[j] = toupper((unsigned char) shmp\->buf[j]);
+
+ /* Post \(aqsem2\(aq to tell the to tell peer that it can now
+ access the modified data in shared memory */
+
+ if (sem_post(&shmp\->sem2) == \-1)
+ errExit("sem_post");
+
+ /* Unlink the shared memory object. Even if the peer process
+ is still using the object, this is okay. The object will
+ be removed only after all open references are closed. */
+
+ shm_unlink(shmpath);
+
+ exit(EXIT_SUCCESS);
+}
+.EE
+.in
+.PP
+.\"
+.SS Program source: pshm_ucase_send.c
+.PP
+The "send" program takes two command-line arguments:
+the pathname of a shared memory object previously created by the "bounce"
+program and a string that is to be copied into that object.
+.PP
+The program opens the shared memory object
+and maps the object into its address space.
+It then copies the data specified in its second argument
+into the shared memory,
+and posts the first semaphore,
+which tells the "bounce" program that it can now access that data.
+After the "bounce" program posts the second semaphore,
+the "send" program prints the contents of the shared memory
+on standard output.
+.PP
+.in +4n
+.EX
+#include <string.h>
+#include "pshm_ucase.h"
+
+int
+main(int argc, char *argv[])
+{
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s /shm\-path string\en", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ char *shmpath = argv[1];
+ char *string = argv[2];
+ size_t len = strlen(string);
+
+ if (len > BUF_SIZE) {
+ fprintf(stderr, "String is too long\en");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Open the existing shared memory object and map it
+ into the caller\(aqs address space */
+
+ int fd = shm_open(shmpath, O_RDWR, 0);
+ if (fd == \-1)
+ errExit("shm_open");
+
+ struct shmbuf *shmp = mmap(NULL, sizeof(struct shmbuf),
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0);
+ if (shmp == MAP_FAILED)
+ errExit("mmap");
+
+ /* Copy data into the shared memory object */
+
+ shmp\->cnt = len;
+ memcpy(&shmp\->buf, string, len);
+
+ /* Tell peer that it can now access shared memory */
+
+ if (sem_post(&shmp\->sem1) == \-1)
+ errExit("sem_post");
+
+ /* Wait until peer says that it has finished accessing
+ the shared memory */
+
+ if (sem_wait(&shmp\->sem2) == \-1)
+ errExit("sem_wait");
+
+ /* Write modified data in shared memory to standard output */
+
+ write(STDOUT_FILENO, &shmp\->buf, len);
+ write(STDOUT_FILENO, "\en", 1);
+
+ exit(EXIT_SUCCESS);
+}
+.EE
+.in
+.PP
.SH SEE ALSO
.BR close (2),
.BR fchmod (2),