Using mutex to synchronize multiple processes

Time:2021-3-3

The function of the following program is to create a piece of shared memory, so that both the parent process and the child process can write data to it. However, it is required that another process can start to write after the parent process or the child process has finished writing, and all of them need to be synchronized.

Key points

  • The memory space occupied by mutex must be shared memory

  • The mutexaddr property must be set to pthread_ PROCESS_ SHARED

  • The memory space occupied by int * * shmptr2 must be shared memory. It holds the pointer to the first piece of shared memory and where it moved.

    The purpose is that after one process finishes writing shared memory, the other process should know where it has written, so that it can continue to write. Otherwise, it will cover the content written by the previous process.

So called shared memory

This piece of memory is in the kernel space, so the child process does not copy this piece of memory; if it is not shared memory, it is the memory in the parent process, then the child process copies it.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main()
{
  pid_t pid;
  int shmid;
  int* shmptr;
  int* tmp;

  int err;
  pthread_mutexattr_t mattr;
  //Create mutex properties
  if((err = pthread_mutexattr_init(&mattr)) < 0)
  {
    printf("mutex addr init error:%s\n", strerror(err));
    exit(1);
  }

  //Let mutex synchronize multiple processes
  //The default property of mutex is synchronous thread, all must have this line of code
  if((err = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED)) < 0)
  {
    printf("mutex addr get shared error:%s\n", strerror(err));
    exit(1);
  }

  //Note: This is a big pit. The mutex here must be created in the way of shared memory, so that the parent process and the child process can share this mutex.
  //Otherwise, the mutex of the parent process is the mutex of the parent process, and the mutex of the child process is the mutex of the child process.
  pthread_mutex_t* m;
  int mid = shmget(IPC_PRIVATE, sizeof(pthread_mutex_t), 0600);
  m = (pthread_mutex_t*)shmat(mid, NULL, 0);

  //Use mutex's properties to create mutex
  if((err = pthread_mutex_init(m, &mattr)) < 0)
  {
    printf("mutex mutex init error:%s\n", strerror(err));
    exit(1);
  }

  //Create a shared memory area for parent and child processes to write data to.
  if((shmid = shmget(IPC_PRIVATE, 1000, IPC_CREAT | 0600)) < 0)
  {
    perror("shmget error");
    exit(1);
  }

  //Gets a pointer to shared memory
  if((shmptr = shmat(shmid, 0, 0)) == (void*)-1)
  {
    perror("shmat error");
    exit(1);
  }

  tmp = shmptr;

  //Create a shared memory and save the pointer to the shared memory above
  int shmid2;
  int** shmptr2;
  if((shmid2 = shmget(IPC_PRIVATE, 20, IPC_CREAT | 0600)) < 0)
  {
    perror("shmget2 error");
    exit(1);
  }
    
  //Gets a pointer to shared memory
  if((shmptr2 = shmat(shmid2, 0, 0)) == (void*)-1)
  {
    perror("shmat2 error");
    exit(1);
  }
  //Let shmptr2 point to the first address of shared memory ID shmid.
  *shmptr2 = shmptr;

  if((pid = fork()) < 0)
  {
    perror("fork error");
    exit(1);
  }
  else if(pid == 0)
  {

    //Start to lock mutex from here. If the lock is successful, the parent process cannot obtain the lock during this period
    if((err = pthread_mutex_lock(m)) < 0)
    {
      printf("lock error:%s\n", strerror(err));
      exit(1);
    }
    for(int i = 0; i < 30; ++i)
    {
      **shmptr2 = i;
      (*shmptr2)++;
    }

    if((err = pthread_mutex_unlock(m)) < 0)
    {
      printf("unlock error:%s\n", strerror(err));
      exit(1);
    }
    exit(0);

  }
  else
  {
    //Lock mutex from this point. If the lock is successful, the child process cannot obtain the lock during this period
    if((err = pthread_mutex_lock(m)) < 0)
    {
      printf("lock error:%s\n", strerror(err));
      exit(1);
    }
    for(int i = 10; i < 42; ++i)
    {
      **shmptr2 = i;
      (*shmptr2)++;
    }
    if((err = pthread_mutex_unlock(m)) < 0)
    {
      printf("unlock error:%s\n", strerror(err));
      exit(1);
    }
  }

  //Destroy child process
  wait(NULL);

  //View the value of shared memory
  for(int i = 0; i < 70; ++i)
  {
    printf("%d ", tmp[i]);
  }

  printf("\n");

  //Destroy mutex properties
  pthread_mutexattr_destroy(&mattr);
  //Destroy mutex
  pthread_mutex_destroy(m);

  exit(0);
}

C / C + + Learning QQ group: 877684253

Recommended Today

Practice analysis of rust built-in trait: partialeq and EQ

Abstract:Rust uses traits in many places, from simple operator overloading to subtle features like send and sync. This article is shared from Huawei cloud community《Analysis of rust built-in trait: partialeq and EQ》Author: debugzhang Rust uses traits in many places, from simple operator overloading to subtle features like send and sync. Some traits can be automatically […]