CS10
CS10
• After exiting the loop, detach the shared memory segment and
releases the writer semaphore o, so that the writer program can
remove the IPC objects.
Header file for svshm_xfr_writer.c and svshm_xfr_reader.c
–––––––svshm/svshm_xfr.h
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include "tlpi_hdr.h"
int bsUseSemUndo = 0;
int bsRetryOnEintr = 1;
if (semid == -1)
{
perror("semget");
exit(0);
}
int bsUseSemUndo = 0;
int bsRetryOnEintr = 1;
static void
usageError(const char *progName, const char *msg)
{
if (msg != NULL)
fprintf(stderr, "%s", msg);
fprintf(stderr, "Usage: %s [-cx] {-f pathname | -k key | -p} "
"seg-size [octal-perms]\n", progName);
fprintf(stderr, " -c Use IPC_CREAT flag\n");
fprintf(stderr, " -x Use IPC_EXCL flag\n");
fprintf(stderr, " -f pathname Generate key using ftok()\n");
fprintf(stderr, " -k key Use 'key' as key\n");
fprintf(stderr, " -p Use IPC_PRIVATE key\n");
exit(EXIT_FAILURE);
}
int
main(int argc, char *argv[])
{
int numKeyFlags; /* Counts -f, -k, and -p options */
int flags, shmid, segSize;
unsigned int perms;
long lkey;
key_t key;
int opt; /* Option character from getopt() */
numKeyFlags = 0;
flags = 0;
case 'p':
key = IPC_PRIVATE;
numKeyFlags++;
break;
case 'x':
flags |= IPC_EXCL;
break;
default:
usageError(argv[0], NULL);
}
}
if (numKeyFlags != 1)
usageError(argv[0], "Exactly one of the options -f, -k, "
"or -p must be supplied\n");
segSize = atoi(argv[optind]);
printf("Sleeping 5 seconds\n");
sleep(5);
exit(EXIT_SUCCESS);
}
svshm_rm.c Program
• The svshm_rm.c program deletes the shared memory segments identified by its command-line arguments.
#include <sys/types.h>
#include <sys/shm.h>
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int j;
exit(EXIT_SUCCESS);
• We begin the shell session by creating two shared memory
segments (100 kB and 3200 kB in size):
• $ ./svshm_create -p 102400
9633796
• $ ./svshm_create -p 3276800
9666565
• $ ./svshm_attach 9633796:0 9666565:0
SHMLBA = 4096 (0x1000), PID = 9903
1: 9633796:0 ==> 0xb7f0d000
2: 9666565:0 ==> 0xb7bed000
Sleeping 5 seconds
Type Control-Z to suspend program
[1]+ Stopped ./svshm_attach 9633796:0 9666565:0
• $ cat /proc/9903/maps
• 1 08048000-0804a000 r-xp 00000000 08:05 5526989 /home/mtk/svshm_attach
• 0804a000-0804b000 r--p 00001000 08:05 5526989 /home/mtk/svshm_attach
• 0804b000-0804c000 rw-p 00002000 08:05 5526989 /home/mtk/svshm_attach
• 2 b7bed000-b7f0d000 rw-s 00000000 00:09 9666565 /SYSV00000000 (deleted)
• b7f0d000-b7f26000 rw-s 00000000 00:09 9633796 /SYSV00000000 (deleted)
• b7f26000-b7f27000 rw-p b7f26000 00:00 0
• 3 b7f27000-b8064000 r-xp 00000000 08:06 122031 /lib/libc-2.8.so
• b8064000-b8066000 r--p 0013d000 08:06 122031 /lib/libc-2.8.so
• b8066000-b8067000 rw-p 0013f000 08:06 122031 /lib/libc-2.8.so
• b8067000-b806b000 rw-p b8067000 00:00 0
• b8082000-b8083000 rw-p b8082000 00:00 0
• 4 b8083000-b809e000 r-xp 00000000 08:06 122125 /lib/ld-2.8.so
• b809e000-b809f000 r--p 0001a000 08:06 122125 /lib/ld-2.8.so
• b809f000-b80a0000 rw-p 0001b000 08:06 122125 /lib/ld-2.8.so
• 5 bfd8a000-bfda0000 rw-p bffea000 00:00 0 [stack]
• 6 ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
In the output from /proc/PID/maps shown in
above Listing , we can see the following:
• Three lines for the main program, shm_attach. These correspond to the
text and data segments of the program 1. The second of these lines is
for a readonly page holding the string constants used by the program.
• Two lines for the attached System V shared memory segments 2.
• Lines corresponding to the segments for two shared libraries. One of
these is the standard C library (libc-version.so) 3. The other is the
dynamic linker (ld-version.so), which we describe in Section 41.4.3 4
• A line labeled [stack]. This corresponds to the process stack 5.
• A line containing the tag [vdso] 6. This is an entry for the linux-gate
virtual dynamic shared object (DSO). This entry appears only in kernels
since 2.6.12. See http://www.trilithium.com/johan/2005/08/linux-gate/
for further information about this entry.
The following columns are shown in each line
of /proc/PID/maps, in order from left
to right:
• A pair of hyphen-separated numbers indicating the virtual address range (in
hexadecimal) at which the memory segment is mapped. The second of
these numbers is the address of the next byte after the end of the segment.
• Protection and flags for this memory segment. The first three letters indicate
the protection of the segment: read (r), write (w), and execute (x). A hyphen
(-) in place of any of these letters indicates that the corresponding
protection is disabled. The final letter indicates the mapping flag for the
memory segment; it is either private (p) or shared (s). For an explanation of
these flags, see the description of the MAP_PRIVATE and MAP_SHARED
flags in Section 49.2. (A System V shared memory segment is always marked
shared.)
• The hexadecimal offset (in bytes) of the segment within the corresponding
mapped file. The meanings of this and the following two columns will
become clearer when we describe the mmap() system call in Chapter 49. For
a System V shared memory segment, the offset is always 0.
• The device number (major and minor IDs) of the device
on which the corresponding mapped file is located.
• The i-node number of the mapped file, or, for System V
shared memory segments, the identifier for the segment.
• The filename or other identifying tag associated with this
memory segment. For a System V shared memory
segment, this consists of the string SYSV concatenated
with the shmget() key of the segment (expressed in
hexadecimal). In this example, SYSV is followed by zeros
because we created the segments using the key
IPC_PRIVATE (which has the value 0). The string (deleted)
that appears after the SYSV field for a System V shared
memory segment is an artifact of the implementation of
shared memory segments.
Shared Memory Associated Data Structure
Each shared memory segment has an associated shmid_ds data structure of
the following
form:
struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment in bytes */
time_t shm_atime; /* Time of last shmat() */
time_t shm_dtime; /* Time of last shmdt() */
time_t shm_ctime; /* Time of last change */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat() / shmdt() */
shmatt_t shm_nattch; /* Number of currently attached processes */
};
Shared Memory Limits
• SHMMNI
This is a system-wide limit on the number of shared memory identifiers (in other
words, shared memory segments) that can be created. (shmget(), ENOSPC)
• SHMMIN
This is the minimum size (in bytes) of a shared memory segment. This limit is
defined with the value 1 (this can’t be changed). However, the effective limit is
the system page size. (shmget(), EINVAL)
• SHMMAX
This is the maximum size (in bytes) of a shared memory segment. The practical
upper limit for SHMMAX depends on available RAM and swap space. (shmget(),
EINVAL)
• SHMALL
This is a system-wide limit on the total number of pages of shared memory.
Most other UNIX implementations don’t provide this limit. The practical upper
limit for SHMALL depends on available RAM and swap space. (shmget(),
ENOSPC)
• SHMSEG
• $ cd /proc/sys/kernel
• $ cat shmmni
4096
• $ cat shmmax
33554432
• $ cat shmall
2097152
Shared Memory Control Operations
• The shmctl() system call performs a range of
control operations on the shared memory
segment identified by shmid.
#include <sys/types.h> /* For portability */
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds
*buf);
Returns 0 on success, or –1 on error
• The cmd argument specifies the control operation to be performed.
The buf argument is required by the IPC_STAT and IPC_SET
operations (described below), and should be specified as NULL for
the remaining operations.
• IPC_RMID
Mark the shared memory segment and its associated shmid_ds
data structure for deletion. If no processes currently have the
segment attached, deletion is immediate; otherwise, the segment is
removed after all processes have detached from it (i.e., when the
value of the shm_nattch field in the shmid_ds data structure falls to
0).
• IPC_STAT
Place a copy of the shmid_ds data structure associated with this
shared memory segment in the buffer pointed to by buf.
• IPC_SET
Update selected fields of the shmid_ds data structure associated
with this shared memory segment using values in the buffer pointed
Locking and unlocking shared memory
A shared memory segment can be locked into RAM, so that
it is never swapped out. This provides a performance
benefit, since, once each page of the segment is
memory-resident, an application is guaranteed never to
be delayed by a page fault when it accesses the page.
There are two shmctl() locking operations:
• The SHM_LOCK operation locks a shared memory
segment into memory.
• The SHM_UNLOCK operation unlocks the shared
memory segment, allowing it to be swapped out.