Using mutex to synchronize multiple processes

Keywords: C

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 after the parent process or the child process finishes writing, another process can start writing, and all of them need to be synchronized.

Key points

  • Memory space occupied by mutex must be shared memory

  • The mutexaddr property must be set to pthread? Process? Shared

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

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

So called shared memory

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

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <string.h>

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
  //mutex's default property is to synchronize threads. 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. Mutex here must be created in the way of shared memory, so that the parent process and child process can share this mutex.
  //Otherwise, the mutex of the parent process is the parent process's, and the mutex of the child process is the child process's, which can't achieve synchronization.
  pthread_mutex_t* m;
  int mid = shmget(IPC_PRIVATE, sizeof(pthread_mutex_t), 0600);
  m = (pthread_mutex_t*)shmat(mid, NULL, 0);

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

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

  //Get 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 of the shared memory above
  int shmid2;
  int** shmptr2;
  if((shmid2 = shmget(IPC_PRIVATE, 20, IPC_CREAT | 0600)) < 0)
  {
    perror("shmget2 error");
    exit(1);
  }
    
  //Get pointer to shared memory
  if((shmptr2 = shmat(shmid2, 0, 0)) == (void*)-1)
  {
    perror("shmat2 error");
    exit(1);
  }
  //Let shmptr2 point to the first address with the shared memory id of 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
  {
    //Start to lock mutex from here. 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 subprocess
  wait(NULL);

  //View shared memory values
  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);
}
QQ group of mutual learning in c/c + +: 877684253 My wechat: xiaoshitou5854

Posted by PatriotXCountry on Fri, 27 Mar 2020 07:53:38 -0700