UNIX Shared Memory and Review

Şerifhan Işıklı
lTunes Tribe
Published in
4 min readSep 11, 2019

Shared memory allows multiple processes to share virtual memory space. In general, one process creates/allocates the shared memory segment. The size and access permissions for the segment are set when it is created. The process then attaches the shared segment, causing it to be mapped into its current data space. If needed, the creating process then initializes the shared memory. Once created, and if permissions permit, other processes can gain access to the shared memory segment and map it into their data space. Each process accesses the shared memory relative to its attachment address.

While the data that these processes are referencing is common, each process will use different attachment address values. When a process is finished with the shared memory segment, it can detach from it. The creator of the segment may grant ownership of the segment to another process. When all processes are finished with the shared memory segment, the process that created the segment is usually responsible for removing it.

The shmget system call is used to create the shared memory segment and generate the associated data structure, or to gain access to an existing segment. The shared memory segment and the system data structure are identified by a unique shared memory identifier that the shmget call returns.

int shmget(key_t key,int size,int shmflg);

New shared memory segment is created if

key = IPC_PRIVATE
key is not associated with an already existing shared memory identifier and IPC_CREAT flag is set (if key is associated, the call will return the id of that shared memory segment)
key is not associated with an already existing shared memory identifier, IPC_CREAT and IPC_EXCL flags are set (if key is associated the call will return error)
key is as above
size is the size of the segment to be created
shmflg is flags as above
At creation time, the system data structure, shmid_ds is generated and initialized

The following program demonstrates creation of shared memory ;

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
main(void) {
key_t key = 15;
int shmid_1, shmid_2;
if ((shmid_1=shmget(key, 1000, 0644|IPC_CREAT)) == -1){
perror(“shmget shmid_1”);
exit(1);
}
printf(“First shared memory identifier is %d \n”, shmid_1);
if ((shmid_2=shmget(IPC_PRIVATE, 20, 0644)) == -1){
perror(“shmget shmid_2”);
exit(2);
}
printf(“Second shared memory identifier is %d \n”, shmid_2);
exit(0);
}

Output :

create shared memory

The shmctl system call permits the user to perform a number of generalized control operations on an existing shared memory segment, and on the system shared memory data structure.

int shmctl(int shmid,int cmd,struct shmid_ds *buf);

shmid is a valid shared memory segment identifier
cmd specifies the operation
buf reference to a structure of type shmid_ds
• Operations are;

o IPC_STAT: return the current values of
shmid_ds
o IPC_SET: modify permissions
o IPC_RMID: remove shared memory
o SHM_LOCK: lock shared memory
o SHM_UNLOCK: unlock shared memory

The system call shmat is used to attach the referenced shared memory segment into the calling process’s data segment:

void *shmat(int shmid,void *shmaddr,int shmflg);

shmid is a valid shared memory identifier
shmaddr is the location of the shared memory segment (0 will let system do it)
shmflg specifies access permissions and alignments (default is read/write permitted)
• If successful, it will return the address of the actual attachment

The system call shmdt detaches the calling process’s data segment from the shared memory segment:

int shmdt(void *shmaddr);

• shmaddr is the reference to a shared memory segment
• returns a value 0 if successful

EXAMPLE

  • A private shared memory segment, 30 bytes in length is created
    • The attachment address and addresses of etext, edata and end are displayed for reference
    • Uppercase alphabetic characters are written to shared memory
    • A child is forked to display contents of shared memory again
    • Child modifies the contents to lowercase letters
    • Parent displays contents again and note that the child does not have to make shmget and shmat

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define SHM_SIZE 30
extern etext, edata, end;
main(void) {
pid_t pid;
int shmid;
char c, *shm, *s;
if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0666)) < 0) {
perror(“shmget fail”);
exit(1);
}
if ((shm = (char *) shmat(shmid, 0, 0)) == (char *) -1) {
perror(“shmat : parent “);
exit(2);
}
printf(“Addresses in parent\n\n”);
printf(“shared mem: %X etext: %X edata: %X end: %X\n\n”,
shm, &etext, &edata, &end);
s = shm; /* s now references shared mem */
for (c = ‘A’; c <= ‘Z’; ++c) /* put some info there */
*s++ = c;
*s = NULL; /* terminate the sequence */
printf(“In parent before fork, memory is : %s \n”, shm);
pid = fork();
switch (pid) {
case -1:
perror(“fork “);
exit(3);
default :
sleep(5);
printf(“\nIn parent after fork, memory is : %s\n”, shm);
printf(“Parent removing shared memory\n”);
shmdt(shm);
shmctl(shmid, IPC_RMID, 0);
exit(0);
case 0 :
printf(“In child after fork, memory is : %s \n”, shm);
for (; *shm; ++shm) /* modify shared memory */
*shm += 32;
shmdt(shm);
exit(0);
}
}

Output :

You can check that examples in online C compiler : https://www.onlinegdb.com/online_c_compiler

Thanks, Have a nice day.

Follow us :

https://medium.com/ltunes

--

--

Şerifhan Işıklı
lTunes Tribe

Senior Software Engineer @Dogus Teknoloji. (Fitness & cycling)