Linux system programming - interprocess communication (shared memory)

The standard pipeline flow, nameless pipeline, named pipeline and mmap memory mapping have been introduced one after another. This article introduces shared memory segments.

1. Shared memory mechanism (shmget)

Shared memory is also a common means of communication between processes (there is no need for inheritance relationship between processes). Generally, OS maps the memory space of the process to different physical memory through memory mapping and page exchange technology, which can ensure the independence of each process and will not be affected by other processes. However, the virtual memory of different processes can be mapped to the same physical memory by sharing memory. One process updates the data in this physical memory, and other processes can immediately see the modified content in this physical memory.

Differences between memory mapping and shared memory:

mmap memory mapping: faster access to files / devices than reading and writing ordinary files. shmget shared memory: communication between multiple processes.

Principle and Implementation:

The shared memory under the system V IPC mechanism is essentially a special memory area. The data to be shared between processes is placed in the shared memory area. All processes that need to access the shared area should map the shared area to the address space of the process. Such a process using shared memory can write information into the space, while another process using shared memory can obtain the information just written through a simple memory read operation, so that an information exchange is carried out between two different processes, so as to realize the communication between processes. Shared memory allows one or more processes to communicate through the memory that appears in their virtual address space at the same time, and the page of this virtual memory is referenced by the page table entry of each shared process. At the same time, it is not necessary to have the same address in the virtual memory of all processes. The access of the process object to the shared memory is controlled by the key, and the access permission is checked by the key.

2. Introduction to related function interfaces of shared memory mechanism

2.1 ftok function

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);

Function function: used to create a keyword that can be associated with a shared memory segment. Parameter introduction: (1) pathname: full path file name, and the file must be accessible. (2) proj_id: usually a non-zero character is passed in. Via pathname and proj_id combination can create a unique key (unique and the same for any process). Return value: If the call is successful, a keyword is returned; otherwise, - 1 is returned.

2.2 shmge function

#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

The shmget function is used to create or open a shared memory segment, which is identified by the first parameter of the function. If the function succeeds, it returns a unique identification number of the shared memory segment (which uniquely identifies the shared memory segment), which is unique and the same for any process.

Parameter introduction (1) Key is a keyword associated with a shared memory segment. If a shared memory segment associated with the specified keyword already exists in advance, the ID of the memory segment will be returned directly. The value of key can be generated by ftok function or IPC_RPIVATE (used to create a shared memory only belonging to the creation process, mainly used for parent-child communication), indicating that new shared memory segments are always created. (2) Size specifies the size of the shared memory segment, in bytes. (3) shmflg is a mask composite value, which can be the combination of access permission value and (IPC_CREAT or IPC_EXCL). IPC_ Creat means to create the memory segment if it does not exist. IPC_ Excl means that if the memory segment exists, the function returns a failure result (- 1).

Return value

If the call is successful, the memory segment ID is returned; otherwise, - 1 is returned.

2.3 shmat function

The shmat function maps the shared memory segment to an address in the process space.

#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);

Note: only administrator user rights can obtain the memory address

parameter (1) shmid is the identification of the shared memory segment and should usually be the successful return value of shmget. (2) shmaddr specifies the location of the shared memory connection to the current process. Usually NULL, indicating that the system is allowed to select the address where the shared memory appears. (3) shmflg is a set of bit identifiers, usually 0. If SHM_RDONLY means read-only mode. The others are read-write mode.

Return value If the call is successful, the first address of the mapped process space is returned; otherwise, (void*)-1 is returned.

2.4 shmdt function

shmdt is used to separate the shared memory segment from the process space, as opposed to the shmat function. Used to close shared memory segments.

#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);

parameter shmaddr is usually the successful return value of shmat. Return value 0 is returned for success and - 1 is returned for failure. Note: it just separates the shared memory, does not delete it, but makes the shared memory no longer available to the current process.

2.5 shmctl function

The function shmctl is a control function of shared memory and can be used to delete shared memory segments.

#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

Parameters:

(1) shmid: the shared memory segment ID should usually be the successful return value of shmget

(2) cmd: operation mode of shared memory segment

IPC_STAT

Get the state of the shared memory and put the shmid of the shared memory_ Copy DS structure to buf

IPC_SET

Change the state of shared memory_ uid, gid and mode in DS structure are copied to shmid in shared memory_ Within DS structure

IPC_RMID

Delete this shared memory

Optional IPC_STAT,IPC_SET,IPC_RMID. Usually IPC_RMID, indicating that the shared memory segment is deleted.

(3) buf: represents the information structure data of the shared memory segment, usually NULL.

For example: shmctl(kshareMem,IPC_RMID,NULL) means to delete the shared memory segment kHareMem

3. Case: basic usage example 1

3.1 example of creating memory segment write data

The following code uses / work / 1 Get the key from the file attribute of DAT as the memory identifier; Then create a shared memory segment, map the memory address, write the data "hello world" to the memory space, and then cancel the mapping. At this time, other processes can access this memory segment and read the data in it.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
int main()
{
    key_t key = ftok("/work/1.dat",1);            	//1. The writer first uses the ftok function to obtain the key
    int shmid = shmget(key,4096,IPC_CREAT); 	//2. The writer uses the shmget function to create a shared memory segment
    printf("key = %d shmid = %d\n", key, shmid);
    char *p = (char *)shmat(shmid, NULL, 0);     //3. Get the first address of the shared memory segment
    memset(p, 0, 4096);                       //  Clear memory space
    memcpy(p, "hello world", 4096);         	   //4. Write content to shared memory segment
    shmdt(p);                               //5. Close the shared memory segment
    return 0;
}

3.2 open memory segment reading example

The following code is used to access the data in the shared memory segment created by the above write side code. The process is the same. If the shmget function judges that the shared memory segment already exists, it will not be created again (it depends on the key as the identifier); Then map the space address, read the data in the memory, print out hello world, and finally destroy the memory space.

#include <stdio.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
int main()
{
    key_t key = ftok("/work/1.dat",1);
    int shmid = shmget(key,4096,IPC_CREAT);
    printf("key = %d shmid = %d\n", key, shmid);
    char *p = (char *)shmat(shmid, NULL, 0);
    printf("receive the data:%s\n",p);		     //4. Read the contents of the shared memory segment
    shmctl(shmid, IPC_RMID, 0);			 //5. Delete shared memory segment
//If the memory space is not deleted, the data will always exist
    return 0;
}

4. Case: basic usage example 2

The above example code obtains the unique key by obtaining the attributes of the file. In fact, you can specify the key yourself as long as the uniqueness is guaranteed.

4.1 example of creating memory write data

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/shm.h>

int main(int argc,char **argv)
{
    /*1. Create shared memory segment*/
    int shmid=shmget(123456,4096,IPC_CREAT);
    /*2. Mapping shared memory to process space*/
    unsigned char *p;
    p=shmat(shmid,NULL,0);
    /*3. Read and write to shared memory*/
    strcpy(p,"Linux Shared memory learning under interprocess communication");
    /*4. Unmap*/
    shmdt(p);
    return 0;
}

4.2 example of opening memory to read data

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/shm.h>

int main(int argc,char **argv)
{
    /*1. Create shared memory segment*/
    int shmid=shmget(123456,4096,IPC_CREAT);
    /*2. Mapping shared memory to process space*/
    unsigned char *p;
    p=shmat(shmid,NULL,0);
    /*3. Read and write to shared memory*/
    printf("p=%s\n",p);
    /*4. Unmap*/
    shmdt(p);
    /*5. Free up shared memory space*/
    shmctl(shmid,IPC_RMID,NULL);
    return 0;
}

Added by ben.hornshaw on Thu, 17 Feb 2022 11:47:10 +0200