Linux - interprocess communication (shared memory)

Shared memory

Shared memory enables different processes to allocate a space in their own virtual address space and map it to the same physical memory space through the kernel object. This physical memory space is accessible to each process mapped to it. (critical resources)

Shared memory allows two unrelated processes to access the same logical memory. Shared memory is a very effective way to share and transfer data between two running processes. The memory shared between different processes is usually arranged as the same section of physical memory. Processes can connect the same piece of shared memory to their own address space, and all processes can access the addresses in the shared memory as if they were allocated by the C language function malloc(). If a process writes data to shared memory, the change will immediately affect any other process that can access the same shared memory.

Use of shared memory

Like semaphores, Linux also provides a set of function interfaces for using shared memory, and the interface using shared coexistence is very similar to that of semaphores, and it is simpler than that of semaphores. They are declared in the header file sys / SHM H medium.
1. Obtain or create kernel objects and determine the size of shared memory (the system allocates physical space according to pages)

int shmget(key_t key, int size, int flag);

Just create kernel objects and apply for physical space

  • key_t key: like the semaphore semget function, the program needs to provide a parameter key (non-zero integer), which effectively names the shared memory segment. Different processes access the same shared memory through the same key value

  • int size: size specifies the amount of memory to be shared in bytes

  • int flag: false is the permission flag. Its function is the same as that of the mode parameter of the open function. If you want to create the shared memory identified by the key when it does not exist, you can work with IPC_CREAT does or operates. The permission flag of shared memory is the same as the read-write permission of files. For example, 0644 indicates that the shared memory created by a process is allowed to be read and written to the shared memory by the process owned by the memory creator. At the same time, the processes created by other users can only read the shared memory.

Return value

  • When the shmget() function succeeds, it returns a shared memory identifier (non negative integer) related to the key for subsequent shared memory functions.
  • Call failed, return - 1

2. Allocate your own virtual address space and map it to the physical space of shared memory

void *shmat(int shmid,const void *addr, int flag);
  • Shmid: shmid is the shared memory ID returned by the shmget() function.
  • void *addr: addr specifies the address where the shared memory is connected to the current process, usually NULL, indicating that the system is allowed to select the address of the shared memory.
  • int flag: flag is a set of flag bits, usually 0.

When the call succeeds, it returns a pointer to the first byte of shared memory. If the call fails, it returns - 1

3. Disconnect the mapping between the current process and the shared memory
The reason for using disconnect instead of delete is that there may be other processes that will continue to use this shared memory

int shmdt(const void *addr);

4. Method of memory sharing

int shmctl(int shmid, int cmd, struct shmid_t *buf);
  • int shmid:shmid is the shared memory identifier returned by the shmget() function.
  • int cmd:command is the action to be taken. It can take the following three values:

IPC_STAT: shmid_ The data in the DS structure is set as the current association value of the shared memory, that is, the shmid is overwritten with the current association value of the shared memory_ The value of DS.
IPC_SET: if the process has sufficient permissions, set the current association value of shared memory to shmid_ The value given in the DS structure
IPC_RMID: delete shared memory segment

  • struct shmid_t *buf:buf is a structure pointer, which points to the structure of shared memory mode and access rights

Because there are connection counters, the shared segment is deleted unless the last process is disconnected from the shared segment. Otherwise, the shared segment will not be deleted, but the kernel object of shared memory will be deleted immediately and cannot be connected to the segment using shmat method.
After a process calls this method to delete, it will not affect the processes previously connected to the shared storage segment

Let's use shared memory for a simple test:

Complete the following process,

Successfully read data in shared memory

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>

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

#include"sem.h"

#define READSEM 1
#define WRITESEM 0

int main()
{
	int shmid = shmget((key_t)1234,128,0664 | IPC_CREAT);
	assert(shmid != -1);

	char *ptr = (char*)shmat(shmid,NULL,0);
	assert(ptr != (char*)-1);
	
	int initVal[] = {1,0};
	int semid = SemGet(1234,intVal,2);
	assert(semid != -1);
	
	//A process write
	while(1)
	{
		SemP(semid,WRITESEM);
		printf("Input:");
		
		fgets(ptr,127,stdin);
		
		SemV(semid,READSEM);
		
		if(strncmp(ptr,"end",3) == 0)
		{
			break;
		}
	}
	
	shmdt(ptr);
	exit(0);
}
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<unistd.h>

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

#include"sem.h"

#define READSEM 1
#define WRITESEM 0

int main()
{
	int shmid = shmget((key_t)1234,128,0664 | IPC_CREAT);
	assert(shmid != -1);

	char *ptr = (char*)shmat(shmid,NULL,0);
	assert(ptr != (char*)-1);
	
	int initVal[] = {1,0};
	int semid = SemGet(1234,intVal,2);
	assert(semid != -1);
	
	//B process read
	while(1)
	{
		SemP(semid,READSEM);
		
		if(strncmp(ptr,"end",3) == 0)
		{
			break;
		}
		
		int i = 0;
		for(;i < strlen(ptr) - 1;i++)
		{
			printf("%c",toupper(ptr[i]));
			fflush(stdout);
			sleep(1);
		}
		printf("\n");
		SemV(semid,WRITESEM);
	}
	
	shmdt(ptr);
	exit(0);
}

From the above code, we can see:
Shared memory is the fastest IPC, and two copies of data are missing in the communication process. (compared to pipeline)

Command management shared memory

View ipcs -m
Delete ipcrm -m shmid

Keywords: Linux

Added by bguzel on Sat, 05 Mar 2022 11:06:53 +0200