How to realize communication between Linux processes

10-16-2023

Shared Memory Shared memory can be said to be the most useful way of inter-process communication and the fastest IPC form. Two different processes A and B share memory, which means that the same physical memory is mapped to the respective process address spaces of processes A and B, and process A can see the update of data in shared memory by process B at the same time, and vice versa.

Because many processes share the same memory area, some synchronization mechanism, mutex and semaphore are necessary.

Benefits: high efficiency, the process can directly read and write memory without copying any data, while communication methods such as pipeline and message queue need to copy data four times in kernel and user space.

And only when unmapping, the content of the shared memory will be written as a memorial.

Shared memory enables different processes to allocate a space on their own virtual address space and map it to the same physical memory space through kernel objects, and this physical memory space is accessible to each process mapped to it. (Critical resources)

Shared memory is to allow 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 physical memory.

Processes can connect the same shared memory to their own address space, and all processes can access the addresses in the shared memory, as if they were allocated by malloc (), a C language function.

If a process writes data to the shared memory, the changes will immediately affect any other process that can access the same shared memory.

Mmap () and its related system call mmap is a memory mapping function provided by linux operating system for user space calls. Many people only know that mmap can complete memory sharing between processes and reduce the number of data copies from user state to kernel state, but they don't deeply understand how mmap is implemented in the operating system and what its principle is.

Using mmap () system call, processes can realize memory sharing by mapping the same common file. After the ordinary file is mapped to the process address space, the process can access the file like ordinary memory without calling read and write operations.

Note: mmap is not designed entirely for IPC, but an application of IPC, which itself provides a way to access and operate ordinary files like ordinary memory.

By using virtual memory segments with special permission sets. When reading and writing this virtual memory segment, the operating system will read and write the corresponding disk file part.

The mmap function creates a pointer to a memory area associated with the contents of a file that can be accessed through an open file descriptor.

The explanation is as follows:

mmap()#include void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

You can change the initial offset value of the data in the file accessed by the shared memory segment by passing the offset parameter.

The descriptor of the opened file is given by the fd parameter.

The amount of data that can be accessed (that is, the length of the memory segment) is set by the length parameter.

You can request the use of a specific memory address through the addr parameter. If its value is zero, the result pointer will be automatically allocated. Failure to follow this practice will reduce the portability of the program, because the available address range is different on different systems.

The prot parameter is used to set the access rights of the memory segment. It is the result of a bitwise OR of the following constant values

PROT_READ memory segment is readable.

PROT_WRITE memory segment is writable.

The PROT_EXEC memory segment is executable.

The PROT_NONE memory segment cannot be accessed.

The influence of flags parameter control program on the change of this memory segment:

The amount of mmap () used to share memory and two ways are as follows:

The memory mapping provided by ordinary files is applicable to any process. To use this method, you need to open or create a file first, and then call ngmmap. The typical calling code is as follows:

fd = open(name.falg.mode); if(fd < 0)ptr = mmap(NULL,len.PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);

The memory mapping provided by special files is suitable for processes with affinity. Because of the special affinity between parent and child processes, mmap and fork are called in the parent process first, then after substituting fork, the child process can inherit the address space anonymously mapped by the parent process and also the address returned by mmap, so that the parent and child processes can communicate through the mapping area. (Note: Generally speaking, the child processes independently maintain some variables inherited from the parent process, while the address returned by mmap () is jointly maintained by the parent and child processes) [Please wait for the blogger to sort out the specific implementation]

Munmap () is used to unmap the memory, canceling the starting address of the mapped memory pointed by the parameter start, and the parameter length is the size of the memory to be canceled. When the process ends or other programs are executed by using the exec related function, the mapped memory will be unmapped automatically, but it will not be unmapped when the corresponding file descriptor is closed.

#include int munmap(void *addr, size_t length);

The use of shared memory is the same as that of semaphore. In Linux, a set of function interfaces are also provided for using shared memory, and the interface using shared coexistence is very similar to that of semaphore, and it is simpler than that using semaphore. They are declared in the header file sys/shm.h

1. Get or create kernel objects, and set the size of shared memory (the system allocates physical space by page).

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

Just create kernel objects and apply for physical space.

Key_t key: Like the semget function of semaphore, the program needs to provide a parameter key (non-zero integer), which effectively names the shared memory segment, and 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.

Intflag: falg is a permission flag, and its function is the same as the mode parameter of the open function. If you want to create the shared memory identified by key, you can do or with IPC_CREAT. The permission flag of the shared memory is the same as the read-write permission of the file, for example, 0644, which means that the shared memory created by one process is allowed to be read and written by the process owned by the memory creator, while the processes created by other users can only read the shared memory.

Return value

After the call is successful, shmget () function will return a non-negative integer, which will be used as the shared memory identifier of subsequent shared memory functions, and this identifier is related to key.

Call failed and returned -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 identifier returned by the shmget () function.

Void *addr:addr specifies the address location where the shared memory is connected to the current process, which is usually NULL, indicating that the system can choose the address of the shared memory.

Intflag: flag is a set of flag bits, usually 0.

Returns a pointer to the first byte of shared memory when the call is successful, and -1 if the call fails.

3. Disconnect the mapping between the current process and shared memory.

The reason why disconnect is used instead of delete is because there may be other processes that will continue to use this shared memory.

int shmdt(const void *addr);

4. Method of operating shared memory

int shmctl(int shmid, int cmd, struct shmid_t *buf);

Int shmid:shmid is the shared memory identifier returned by shmget () function.

Int cmd:command is the operation to be taken, which can take the following three values:

IPC_STAT: Set the data in the shmid_ds structure as the current associated value of shared memory, that is, overwrite the value of shmid_ds with the current associated value of shared memory.

IPC_SET: If the process has enough rights, set the current associated value of the shared memory to the value given in the shmid_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 of the connection counter, the shared segment is deleted unless the last process disconnects from it. Otherwise, the shared segment will not be deleted, but the kernel object of shared memory will be deleted immediately, and the shmat method cannot be used to connect with the segment.

After a process calls this method to delete, it will not affect the processes that have been connected to the shared storage segment before.

Let's use shared memory for a simple test:

Complete the following process,

Successfully read data in shared memory.

#include#include#include#include#include#include#include#include#include"sem.h"#define READSEM 1#define WRITESEM 0int 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 writes 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#include#include#include#include#include#include#include#include"sem.h"#define READSEM 1#define WRITESEM 0int 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 reads 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(" "); 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 lost during communication. (Compared with pipes)

Command Management Shared Memory View ipcs -m

Delete ipcrm -m shmid

Copyright Description:No reproduction without permission。

Knowledge sharing community for developers。

Let more developers benefit from it。

Help developers share knowledge through the Internet。

Follow us