Shared memory is one of the simplest methods for inter-process communication. The shared memory allows two or more processes to access the same memory, just as the malloc () function returns a pointer to the same physical memory area to different processes. When a process changes the content of this address, other processes will notice this change.
Fast local communication
Because all processes share the same memory, the shared memory has the highest efficiency among various inter-process communication methods. Accessing the shared memory area is as fast as accessing the memory area exclusive to the process, and does not need to be completed through system calling or other processes that need to be switched to the kernel. It also avoids unnecessary data replication.
Because the system kernel does not synchronize access to the shared memory, you must provide your own synchronization measures. For example, before data is written, the process is not allowed to read information from the shared memory, and the two processes are not allowed to write data to the same shared memory address at the same time. A common method to solve these problems is to use semaphores for synchronization. However, there is only one process in our program that accesses the shared memory. Therefore, while demonstrating the shared memory mechanism in a centralized manner, we can avoid confusion in the Code Synchronization logic.
Memory Model
To use a shared memory, the process must first allocate it. Then every process that needs to access the shared memory block must bind the shared memory to its own address space. After the communication is completed, all processes will be out of the shared memory and a process will release the shared memory block.
Understanding the Linux memory model can help explain the binding process. In Linux, the virtual memory of each process is divided into many pages. These memory pages contain actual data. Each process maintains a ing from the memory address to the Virtual Memory Page. Although each process has its own memory address, different processes can map the same memory page to their own address space at the same time to share the memory.
Allocating a new shared memory block will create a new memory page. Because all processes want to share access to the same memory, only one process should create a new shared memory. Allocating an existing memory block again does not create a new page, but returns an identifier that identifies the memory block. If a process needs to use this shared memory block, it must first be bound to its own address space. This will create a ing from the virtual address of the process itself to the shared page. After the shared memory is used up, the ing is deleted. When no process needs to use this shared memory block, one (and only one) process must be responsible for releasing the shared memory page.
The size of all shared memory blocks must be an integer multiple of the system page size. System page size refers to the number of bytes contained in a single memory page in the system. In Linux, the memory page size is 4 kb, but you should still obtain this value by calling getpagesize.
Allocate
A process allocates a shared memory block by calling shmget (shared memory get. The first parameter of this function is a key value used to identify the shared memory block. Processes that are independent of each other can obtain access to the same shared memory block by specifying the same key. Unfortunately, other programs may also select the same specific value as their own shared memory key value, resulting in a conflict. Using the special constant ipc_private as the key value can ensure that the system creates a new shared memory block. The second parameter of this function specifies the size of the applied memory block. Because these memory blocks are allocated in pages, the size of actually allocated memory blocks will be extended to an integer multiple of the page size.
The third parameter is a set of labels that use the bitwise OR operation of a specific constant for shmget. These specific constants include:
Ipc_creat: indicates that a new shared memory block should be created. By specifying this flag, we can create a new shared memory block with the specified key value. Ipc_excl: this flag can only be used with ipc_creat. When this flag is specified, if a shared memory block with this key value already exists, the shmget call will fail. That is to say, this sign will allow the thread to obtain a "exclusive" shared memory block. If this flag is not specified and a shared memory block with the same key value exists in the system, shmget returns the created shared memory block instead of creating a new one. Mode flag: this value is composed of nine digits, indicating the access permissions of the owner, group, and other users to the memory block. The bit of the execution permission is ignored. An easy way to specify the access permission is to use the constant specified in <sys/STAT. h> and specified in the stat entry in Section 2 of the manual page. For example, s_irusr and s_iwusr specify the read and write permissions of the memory block owner, while s_iroth and s_iwoth specify the read and write permissions of other users. In the following example, the shmget function creates a new shared memory block (when the shm_key is occupied, access to an existing shared memory block is obtained ), only the owner has read and write permissions on the memory block, and other users cannot read and write.
Int segment_id = shmget (shm_key, getpagesize (), ipc_creat | s_irusr | s_iwusr); if the call is successful, shmget returns a shared memory identifier. If the shared memory block already exists, the system checks the access permission and checks whether the block is marked as waiting for destruction.
Binding and detachment
To allow a process to obtain access to a shared memory, the process must first call shmat (shared memory attach, bound to the shared memory ). Pass the shared memory identifier shmid returned by shmget to this function as the first parameter. The second parameter of this function is a pointer pointing to the process memory address that you want to map to the shared memory block. If you specify NULL, Linux automatically selects a suitable address for ing. The third parameter is a flag that includes the following options:
Shm_rnd indicates that the address specified by the second parameter should be rounded down to an integer multiple of the memory page size. If you do not specify this flag, you will have to manually align the size of the shared memory block by page size when calling shmat. Shm_rdonly indicates that the memory block will only allow read operations and prohibit writing. If this function is successfully called, the address corresponding to the bound shared memory block is returned. The sub-processes created by using the fork function inherit these shared memory blocks at the same time. If necessary, they can take the initiative to leave these shared memory blocks. When a process no longer uses a shared memory block, it should call the shmdt (shared memory detach) function to remove it from the shared memory block. Pass the address returned by the shmat function to this function. If the process for releasing the memory block is the last process that uses the memory block, the memory block will be deleted. Calls to exit or any exec functions will automatically remove the process from the shared memory block.
Control and release shared memory blocks
Call the shmctl ("shared memory control" to control the shared memory) function to return information about a shared memory block. At the same time, shmctl allows the program to modify this information. The first parameter of this function is a shared memory block identifier.
To obtain information about a shared memory block, ipc_stat is passed as the second parameter for this function, and a pointer to a struct shmid_ds object is passed as the third parameter.
To delete a shared memory block, use ipc_rmid as the second parameter and null as the third parameter. When the last process bound to the shared memory block is detached from it, the shared memory block will be deleted.
You should use shmctl to release each shared memory block to prevent exceeding the total number of shared memory blocks allowed by the system. Calling exit and exec will remove the process from the shared memory block, but will not delete the memory block. For details about other operations on shared memory blocks, refer to the manual page of The shmctl function.
Sample program
The program in code 5.1 demonstrates the use of shared memory blocks. </P> <p> code 5.1 (SHM. c) try to share the memory </P> <p> # include <stdio. h> </P> <p> # include <sys/SHM. h> </P> <p> # include <sys/STAT. h> </P> <p> int main () </P> <p >{</P> <p> int segment_id; </P> <p> char * shared_memory; </P> <p> struct shmid_ds shmbuffer; </P> <p> int segment_size; </P> <p> const int shared_segment_size = 0x6400;/* allocate a shared memory block */</P> <p> segment_id = shmget (ipc_private, shared_segment_size, ipc_creat | ipc_excl | s_irusr | s_iwusr);/* bind to the shared memory block */</P> <p> shared_memory = (char *) shmat (segment_id, 0, 0 ); </P> <p> printf ("shared memory attached at address % P/N", shared_memory ); /* determine the size of the shared memory */</P> <p> shmctl (segment_id, ipc_stat, & shmbuffer); </P> <p> segment_size = shmbuffer. shm_segsz; </P> <p> printf ("segment size: % d/N", segment_size); </P> <p> sprintf (shared_memory, "Hello, world. ");/* write a string in the shared memory */</P> <p> shmdt (shared_memory ); /* remove the shared memory block */</P> <p> shared_memory = (char *) shmat (segment_id, (void *) 0x500000, 0 ); /* re-bind the memory block */</P> <p> printf ("Shared Memory reattached at address % P/N", shared_memory ); </P> <p> printf ("% s/n", shared_memory);/* output the string in the shared memory */</P> <p> shmdt (shared_memory ); /* remove the shared memory block */</P> <p> shmctl (segment_id, ipc_rmid, 0 ); /* release the shared memory block */</P> <p> return 0; </P> <p >}</P> <p>
Debugging
The IPCS command can be used to view information about inter-process communication mechanisms, including shared memory, in the system. Specify the-M parameter to obtain information about the shared memory. For example, the following example indicates that a shared memory block numbered 1627649 is in use:
% IPCS-M ------ shared memory segments -------- key shmid owner perms bytes nattch status 0x00000000 1627649 user 640 25600 0 if the shared memory block is not deleted after the program ends, it is incorrectly protected stay, you can use the ipcrm command to delete it.
% Ipcrm SHM 1627649
Advantages and disadvantages
Shared memory blocks provide an efficient two-way communication mechanism between any number of processes. Each user can read and write data, but all programs must comply with certain protocols to prevent the occurrence of competitive states such as overwriting memory space before reading information. Unfortunately, Linux cannot strictly guarantee exclusive access to shared memory blocks, even when you create a new shared memory block using ipc_private. At the same time, multiple processes that use shared memory blocks must use the same key value.