• One of the simplest interprocess communication methods
is using shared memory.
• Shared memory allows two or more processes to access
the same memory as if they all called malloc and were returned pointers to the
same actual memory.
• When one process changes the memory, all the other
processes see the modification.
• Shared memory is the fastest form of interprocess
communication because all processes share the same piece of memory.
– Access to this shared memory is as fast as accessing a
process’s nonshared memory, and it does not require a system call or entry to
the kernel. It also avoids copying data unnecessarily.
• Because the kernel does not synchronize accesses to
shared memory, you must provide your own synchronization.
– For example, a process should not read from the memory
until after data is written there, and two processes must not write to the same
memory location at the same time. A common strategy to avoid these race
conditions is to use semaphores
Shared
memory allocation
• A process allocates a shared memory segment using
shmget (“SHared Memory GET”).
– Its first parameter is an integer key that specifies
which segment to create.
– Its second parameter specifies the number of bytes in
the segment. Because segments are allocated using pages, the number of actually
allocated bytes is rounded up to an integral multiple of the page size.
– The third parameter is the bitwise or of flag values
that specify options to shmget. The flag values include these:
• IPC_CREAT—this flag indicates that a new segment
should be created.
• Mode flags—this value is made of 9 bits indicating
permissions (R, W, X) granted to owner, group, and world to control access to
the segment. .An easy way to specify permissions is to use the constants
defined in <sys/stat.h>.
• For
e.g. S_IRUSR and
S_IWUSR specify read and write permissions for the owner of the shared memory segment,
and S_IROTH and S_IWOTH specify read and write permissions for others.
– E.g
int segment_id = shmget (shm_key, getpagesize (),
IPC_CREAT | S_IRUSR | S_IWUSER);
• If the call succeeds, shmget returns a segment
identifier.
– Synopsis
• #include <sys/ipc.h>
• #include <sys/shm.h>
• int
shmget(key_t key, size_t size, int
shmflg);
Attachment
and detachment
• To make the shared memory segment available, a process
must use shmat, “Shared Memory ATtach.”
– First parameter is the shared memory segment
identifier SHMID returned by shmget.
– The second argument is a pointer that specifies where
in your process’s address space you want to map the shared memory; if you
specify NULL, Linux will choose an available address.
– The third argument is a flag, which can include the following:
• SHM_RND indicates that the address specified for the
second parameter should be rounded down to a multiple of the page size. If you
don’t specify this flag, you must page-align the second argument to shmat
yourself.
• SHM_RDONLY indicates that the segment will be only
read, not written.
– If the call succeeds, it returns the address of the
attached shared segment.
– Synonpsis
• #include <sys/types.h>
• #include <sys/shm.h>
• void
*shmat(int shmid, const void *shmaddr,
int shmflg);
Dettachment
• When you’re finished with a shared memory segment, the
segment should be detached using shmdt (“SHared Memory DeTach”).
– Pass it the address returned by shmat.
– If the segment has been deallocated and this was the
last process using it, it is removed.
– Calls to exit and any of the exec family automatically
detach segments.
– Synopsis
• #include <sys/types.h>
• #include <sys/shm.h>
• int
shmdt(const void *shmaddr);
Controlling and Deallocating
Shared Memory
• The shmctl (“SHared Memory ConTroL”) call returns information
about a shared memory segment and can modify it.
– The first parameter is a shared memory segment
identifier.
– The
second parameter is the operation to be performed on the shared memory
• IPC_STAT To obtain information about a shared memory segment,
• IPC_SET Write the values of some members of the shmid_ds
structure pointed to by buf to the kernel data structure associated with
this shared memory segment
• IPC_RMID Remove the segment
• The segment is removed when the last process that has
attached it finally detaches it.
• Each shared memory segment should be explicitly
deallocated using “shmctl” when you’re finished with it, to avoid violating the
system wide limit on the total number of shared memory segments. Invoking exit
and exec detaches memory segments but does not deallocate them.
• SYNOPSIS
– #include <sys/ipc.h>
– #include <sys/shm.h>
– int shmctl(int
shmid, int cmd, struct shmid_ds *buf);
– The buf argument is a pointer to a shmid_ds
structure, defined in <sys/shm.h> as follows:
– struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions
*/
size_t
shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat/shmdt */
shmatt_t shm_nattch; /* No. of current attaches */ ...
};
Example
of shared memory
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ()
{ int
segment_id;
char* shared_memory;
struct
shmid_ds shmbuffer;
int
segment_size;
const
int shared_segment_size = 0x6400;
/*
Allocate a shared memory segment. */
segment_id
= shmget (IPC_PRIVATE, shared_segment_size,
IPC_CREAT
| IPC_EXCL | S_IRUSR | S_IWUSR);
/* Attach
the shared memory segment. */
shared_memory
= (char*) shmat (segment_id, 0, 0);
printf
(“shared memory attached at address %p\n”, shared_memory);
/*
Determine the segment’s size. */
shmctl
(segment_id, IPC_STAT, &shmbuffer);
segment_size
= shmbuffer.shm_segsz;
printf
(“segment size: %d\n”, segment_size);
/*
Determine the segment’s size. */
shmctl
(segment_id, IPC_STAT, &shmbuffer);
segment_size
= shmbuffer.shm_segsz;
printf
(“segment size: %d\n”, segment_size);
/* Write a string to the shared memory segment. */
sprintf
(shared_memory, “Hello, world.”);
/* Detach the shared memory segment. */
shmdt
(shared_memory);
/* Reattach the shared memory segment, at a different
address. */
shared_memory
= (char*) shmat (segment_id, (void*) 0x5000000, 0);
printf
(“shared memory reattached at address %p\n”, shared_memory);
/* Print out the string from shared memory. */
printf
(“%s\n”, shared_memory);
/* Detach the shared memory segment. */
shmdt
(shared_memory);
/* Deallocate the shared memory segment. */
shmctl
(segment_id, IPC_RMID, 0);
return
0;
}
Debugging
• The “ipcs” command provides information on
interprocess communication facilities, including shared segments.
• Use the -m flag to obtain information about shared
memory. For example, this code illustrates that one shared memory segment,
• numbered 1627649, is in use:
• $ ipcs -m
------ Shared Memory Segments --------
key
shmid owner perms
bytes nattch status
0x00000000 1627649
user 640 25600
0
• If this memory segment was erroneously left behind by
a program, you can use the “ipcrm” command to remove it.
• $ipcrm shm 1627649
Pros
and cons of share memory
• Shared memory segments permit fast bidirectional
communication among any number of processes.
• Each user can both read and write, but a program must
establish and follow some protocol for preventing race conditions such as
overwriting information before it is read.
• Also, for multiple processes to use a shared segment,
they must make arrangements to use the same key
No comments:
Post a Comment