Shared Memory and Semaphores in Unix

System Calls

Disclaimer: It is possible that this description contains errors in prototypes. See the man pages for any discrepancies or questions.

For shared memory and semaphores, you must include the following libraries: <sys/types.h>, <sys/ipc.h>,<sys/errno.h>,<stdio.h>, <sys/shm.h>, and <sys/sem.h>.
 

System calls usually return -1 if the call failed and set the global variable errno to the error returned by the kernel. The values that errno can take along with a brief description of each error can be found in the header file <sys/errno.h>.You must test the return value from each system call for success.
 

IPC objects are message queues, semaphores, and shared memory segments. Shared memory and semaphores are described on this page. Shared memory and semaphores are requested from the operating system.

To refer to the IPC structure in the kernel, a nonnegative integer called an identifier is used. An IPC key identifies an IPC object to be used for sharing among multiple processes. The assignment is permanent. You must return them explicitly.

Functions for Semaphores

For every semaphore required by your program, you must obtain the semaphore from the system and give the semaphore an initial value.

The semget function either creates a new semaphore or returns the identifier of an existing semaphore. In your program, you will only be using semget to create a new semaphore for each semaphore required.
 
 

int semget(key_t key, int nsems, int semflg);
 
 

In your program :
 
 

#define SEMPERM 0600 /* permission for semaphore */

int semid;

semid = semget(IPC_PRIVATE,1,SEMPERM|IPC_CREAT|IPC_EXCL);

By specifying IPC_PRIVATE for the key, the operating system will create a brand new IPC structure. This is used in a parent-child relationship. The parent creates a new IPC structure by specifying IPC_PRIVATE and the resulting identifier is then available to the child after the fork.

The low-order 9 bits of the semflag are permissions: rwx for owner, group, and everyone else. We are setting the permissions to read and write for the owner. IPC_CREAT and IPC_EXCL flags are required to ensure that a new IPC structure will be created (making sure we don't reference an existing structure with the same identifier).
 
 

You must set each semaphore to an initial value. To do this, you will need to create a union as described below and call the procedure semctl.
 
 

union {

int val;

struct semid_ds *buffer;

ushort *array;

}semnum;

semnum.val = your initialization value;

semctl(semid,0,SETVAL, semnum);
 
 

At the completion of the processing the program should return the semaphores. This is very important as the system has a fixed number of semaphores and if you do not return them, others cannot use them and the system will eventually run out. The semctl procedure is also used to return the semaphore to the system:

semctl(semid,0,IPC_RMID,NULL);

To perform the wait on the semaphore, you should use the following procedure:

void p(int semid)

{

struct sembuf p_buf;

p_buf.sem_num = 0;

p_buf.sem_op = -1;

p_buf.sem_flg = 0;

if (semop(semid,&p_buf,1) < 0)

{

printf("fatal p error on semaphore %i",semid);

}

}
 
 

sembuf is defined in sem.h.
 
 

To Signal the semaphore, use the following procedure:
 
 

void v(int semid)

{

struct sembuf v_buf;

v_buf.sem_num = 0;

v_buf.sem_op = 1;

v_buf.sem_flg = 0;

if(semop(semid,&v_buf, 1) < 0)

{

printf("fatal v error on semaphore %i",semid);

}

}

I would suggest modifying p and v to return the value returned by semop so the caller knows whether p and v were successful.
 
 

See the man pages for more information

Functions for Shared Memory


 
 

To obtain a segment of memory that can be used for sharing:

#define SHMPERM 0600

int segid;

segid= shmget (IPC_PRIVATE,size,IPC_CREAT|IPC_EXCL|SHMPERM);
 
 

See above for an explanation of IPC_Private, IPC_CREAT, IPC_EXCL, and SHMPERM.

You should define size the size of the block required.
 
 

Before the shared memory can be used, it must be attached to all of the processes that are to use it. It can be attached before or after the fork.
 
 

char * buf;

buf = (char *)shmat (segid, (char *)0,0);
 
 

As with semaphores, the shared segment must be returned prior to termination:
 
 

shmctl(segid,IPC_RMID,NULL);
 
 

Semaphores and shared segments are "permanent." As you try to get your program to run, you will probably get some and your program will crash before it returns them. Use the system utility programs ipcs and ipcrm to clean up after yourself. If you do not, the system will run out of semaphores and/or shared segments and no one else will be able to get any (including you). Needless to say, your classmates (and others) will not be happy with you.
 
 

ipcs: report interprocess communication facilities status
 
 

ipcrm: removes a message queue, semaphore set, or shared memory ID.

You can also execute:
cs326clean

It is a script written by a former CS326 student.

Above, you are given the details of the system calls you to use shared memory and shared semaphores. You can use man followed by procedure name on the Unix command line to obtain additional information regarding any of the system calls.


Last modified 1:28 PM 11/07/2024

This page is copyright protected © by Barbara Bracken