MetallicPriest
MetallicPriest

Reputation: 30835

Interprocess mutex with pthreads

I want to use a mutex which will be used to synchronize access to some variables residing in the memory shared b/w two different processes. How can I achieve that. Code sample to perform that will be very appreciated.

Upvotes: 5

Views: 16869

Answers (3)

Ben
Ben

Reputation: 11

As the reply from Changbin Du in the previous answer,

The mutex must be placed at shared memory(anoymous or file mapped) but not a global var.

Here is the demo:

// The mutex must be placed at shared memory(anoymous or file mapped) but not a global var
pthread_mutex_t *shm_lock;

void child_start()
{
   pthread_mutex_lock(shm_lock);

   printf("Child process has started\n");
   sleep(1);
   printf("Child process has finished\n");

   pthread_mutex_unlock(shm_lock);
}

void parent_start()
{
   pthread_mutex_lock(shm_lock);

   printf("Parent process has started\n");
   sleep(1);
   printf("Parent process has finished\n");

   pthread_mutex_unlock(shm_lock);
}

int main(void)
{
   // init shared lock at anoymous shared memory
   shm_lock = (pthread_mutex_t*) mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);

   pthread_mutexattr_t attr;
   pthread_mutexattr_init(&attr);
   pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
   pthread_mutex_init(shm_lock, &attr);
   pthread_mutexattr_destroy(&attr);

   pid_t pid = fork();
   if (pid == 0)
   {
      child_start();
      return 0;
   }

   parent_start();
   wait(NULL);

   pthread_mutex_destroy(shm_lock);
   return 0;
}

Then, the correct log will be printed.

Parent process has started
Parent process has finished
Child process has started
Child process has finished

Upvotes: 1

cnicutar
cnicutar

Reputation: 182754

Use a POSIX semaphore initialized to 1 instead. (See below) Use sem_init for unnamed semaphores or sem_open for named ones.

sem_t sem;

/* initialize using sem_init or sem_open */

sem_wait(&sem);
/* critical region */
sem_post(&sem);

Many years after initially posting this answer, it has to be updated.

Mutexes should actually be used instead of semaphores. R and kuga's comments (copied verbatim below) explain why. In particular I find kuga's mention that mutexes can only be posted by their locking thread most compelling.


R

sem_init requires a nonzero pshared argument to be shared, just like a mutex would require the pshared attribute. There's no reason to prefer semaphores over mutexes for this, and in fact mutexes would be better because you could use a robust mutex which allows you to handle the (very real!) case where one process dies while holding the lock.

kuga

Additionally to R..`s post, a mutex can only be posted by the thread that locks it. This is often required and a semaphore does not provide this feature. So this is not the correct answer, Jeff´s answer should be flagged as the correct answer.

Upvotes: 8

Jeff Hammond
Jeff Hammond

Reputation: 5652

The following example demonstrates the creation, use and destruction of a Pthread interprocess mutex. Generalizing the example for multiple processes is left as an exercise for the reader.

#include <pthread.h>

pthread_mutex_t shm_mutex;

int main(void)
{
    int err;
    pthread_mutexattr_t attr;
    err = pthread_mutexattr_init(&attr); if (err) return err;
    err = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); if (err) return err;
    err = pthread_mutex_init(&shm_mutex, &attr); if (err) return err;
    err = pthread_mutexattr_destroy(&attr); if (err) return err;
    err = pthread_mutex_lock(&shm_mutex); if (err) return err;
    err = pthread_mutex_unlock(&shm_mutex); if (err) return err;
    err = pthread_mutex_destroy(&shm_mutex); if (err) return err;
    return 0;
}

Upvotes: 15

Related Questions