Mike
Mike

Reputation: 825

Destroying shared memory segment with shmctl() (Linux)

I'm having trouble figuring this out. I have some code modelling the Producer/Consumer problem which uses semaphores (P() and V() are just the usual wait() and signal() functions, respectively).

I allocate some memory for a buffer I use in the implementation, but I don't understand how to properly destroy the allocated space once the program exits. This creates problems when I run the program a second time where either the old data remains in memory, or even an error pops up which doesn't allow me to allocate the shared space again.

Here's the code:

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdlib.h>

#include "sem.h"


#define N 3
#define BUFSIZE 1  
#define PERMS 0666 //0666 - To grant read and write permissions 

int *buffer;
int nextp=0,nextc=0;
int mutex,full,empty;    /* semaphore variables
                          * mutex - binary semaphore -- critical section
                          * full, empty - counting semaphore */

void producer()
{
 int data;
 if(nextp == N)
    nextp=0;
 printf("\nEnter the data(producer) :");
 scanf("%d",(buffer+nextp));
 nextp++;
 }

void consumer()
{
 int g;
 if(nextc == N)
    nextc=0;
 g=*(buffer+nextc++);
 printf("\nconsumer consumes the data:%d\n",g);
}

int main()
{
 int shmid,no=1,i;
 int pid,n;

 if((shmid=shmget(1000,BUFSIZE,IPC_CREAT | PERMS)) < 0)
 {
  printf("\n unable to create shared memory");
  return;
 }
 if((buffer=(int*)shmat(shmid,(char*)0,0)) == (int*)-1)
 {
  printf("\n Shared memory allocation error\n");
  exit(1);
 }

 // semaphore creation
 if((mutex=semget(IPC_PRIVATE,1,PERMS | IPC_CREAT)) == -1)
 {
   printf("\n can't create mutex semaphore");
   exit(1);
 }

 if((empty=semget(IPC_PRIVATE,1,PERMS | IPC_CREAT)) == -1)
 {
  printf("\n can't create empty semaphore");
  exit(1);
 }

 if((full=semget(IPC_PRIVATE,1,PERMS | IPC_CREAT)) == -1)
 {
  printf("\ncan't create full semaphore");
  exit(1);
 }

 // initialze the semaphore     
 sem_create(mutex,1);
 sem_create(empty,N);
 sem_create(full,0);


//forking a child 
 if((pid=fork()) < 0)
 {
  printf("\n Error in process creation");
  exit(1);
 }

//Producer process
 if(pid > 0)
 {
    for(i=0;i<N;i++)
    {
      P(empty); 
      P(mutex); // Entering critical section
      producer();
      V(mutex); // Exit from critical section
      V(full); 
    }
    wait();
    semkill(mutex);
    semkill(empty);
    semkill(full);
    shmdt(0);
    shmctl(shmid, IPC_RMID, NULL);
 }

//consumer process
    if(pid == 0)
    {
     for(i=0;i<N;i++)
     {
      P(full);
      P(mutex); // Entering critical section
      consumer();
      V(mutex);
      V(empty); // Exit from critical section
     }
  }
}

Upvotes: 2

Views: 2220

Answers (1)

user3433763
user3433763

Reputation: 31

You're detaching a NULL pointer. You need to detach the address returned by shmat(). Also, you may want to mark the segment for destruction where it's created, that way exit can handle the detach as well, which reduces the chance of memory getting limbo'd when the unexpected happens. You should probably still detach manually.

// ...create shared memory segment...

// attach.
buffer = shmat(shmid, 0, 0);
// mark for destruction.
shmctl(shmid, IPC_RMID, 0);

// ...do stuff...

// detach.
shmdt(buffer);

Upvotes: 3

Related Questions