diff options
| author | Michael Kerrisk <mtk.manpages@gmail.com> | 2020-02-28 16:07:24 +0100 |
|---|---|---|
| committer | Michael Kerrisk <mtk.manpages@gmail.com> | 2020-03-12 09:24:44 +0100 |
| commit | 145b262dda5c57b57ab112d3f656cdef6bb06816 (patch) | |
| tree | 8b2b6148e61f2d8a96e90be3befa90ef6df77c9c /man3 | |
| parent | e5d8f6046b7b675f4ed4a97ff4e84a3d3b02edae (diff) | |
| download | man-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.3 | 218 |
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), |
