mirror of https://github.com/mkerrisk/man-pages
shm_open.3: EXAMPLE: add some example programs
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
parent
e5d8f6046b
commit
145b262dda
218
man3/shm_open.3
218
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),
|
||||
|
|
Loading…
Reference in New Issue