Here's another way to explain interprocess communication, using shared memory.
One, what is shared memory
Shared memory, as the name implies, allows two unrelated processes to access the same logical memory. Shared memory is a very efficient way to share and pass data between two running processes. Memory that is shared between different processes is usually scheduled as the same piece 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 changes will immediately affect any other process that can access the same piece of shared memory.
Special reminder: Shared memory does not provide a synchronization mechanism, that is, there is no automatic mechanism to prevent the second process from reading the shared memory until the first process finishes writing it. So we usually need to use other mechanisms to synchronize access to shared memory, such as the amount of semaphores mentioned earlier. For more information on semaphores, you can check out another article: Linux interprocess communication-using semaphores
second, the sharing of memory makes
As with semaphores, a set of function interfaces is provided in Linux for use with shared memory, and interfaces with shared coexistence are very similar to semaphores and are simpler than interfaces that use semaphores. They are declared in the header file sys/shm.h .
1. Shmget () function
This function is used to create shared memory, which is prototyped as:
int shmget(key_t key, size_t size, int shmflg);
The first parameter, like the Semget function of the semaphore, requires that the program provide a parameter key (not a 0 integer) that effectively names the shared memory segment, and the Shmget () function returns a shared memory identifier (non-negative integer) associated with key when successful, for subsequent shared memory functions. The call failed to return-1.
Unrelated processes can access the same shared memory through the return value of the function, which represents a resource that the program may want to use, and the program accesses all shared memory indirectly, by calling the Shmget () function and providing a key, and then the system generates a corresponding shared memory identifier (Shmget ( ), only the Shmget () function uses the semaphore key directly, and all other semaphore functions use the semaphore identifier returned by the Semget function.
The second parameter, size specifies the amount of memory that needs to be shared in bytes
The third parameter, SHMFLG, is the permission flag, which functions like the mode parameter of the Open function, and can be done or manipulated with ipc_creat if it is to be created if the shared memory identified by the key does not exist. The permission flags for shared memory are the same as the read and write permissions for a file, for example, 0644, which means that shared memory that is allowed to be created by a process is read and written to shared memory by processes owned by the memory creator, while processes created by other users can read only shared memory.
2, Shmat () function--At:attach
When the shared memory is created for the first time, it cannot be accessed by any process, and the Shmat () function is used to initiate access to the shared memory and to connect the shared memory to the address space of the current process. Its prototype is as follows:
void *shmat(int shm_id, const void *shm_addr, int shmflg);
The first parameter, shm_id, is the shared memory identity returned by the Shmget () function.
The second parameter, SHM_ADDR, specifies that the shared memory is connected to the address location in the current process, which is usually empty, indicating that the system chooses the address of the shared memory.
The third parameter, SHM_FLG, is a set of flag bits, typically 0.
When the call succeeds, returns a pointer to the first byte of shared memory if the call fails to return-1.
3, SHMDT () function--Dt:detach
This function is used to detach shared memory from the current process. Note that separating shared memory is not removing it, just making that shared memory no longer available to the current process. Its prototype is as follows:
int shmdt(const void *SHMADDR);
The parameter shmaddr is the address pointer returned by the Shmat () function, returns 0 when the call succeeds, and returns-1 on failure.
4, Shmctl () function--Ctl:control
As with the semaphore Semctl () function, it is used to control shared memory, which is prototyped as follows:
int shmctl(int shm_id, int command, struct shmid_ds *buf);
The first argument, shm_id, is the shared memory identifier returned by the Shmget () function.
The second argument, command is the action to take, it can take the following three values:
- Ipc_stat: Sets the data in the SHMID_DS structure to the current associated value of shared memory, which overwrites the value of Shmid_ds with the current associated value of shared memory.
- Ipc_set: If the process has sufficient permissions, set the current association value of shared memory to the value given in the SHMID_DS structure
- IPC_RMID: Deleting shared memory segments
The third parameter, buf, is a struct pointer that points to the structure of shared memory mode and access permissions.
The SHMID_DS structure includes at least the following members:
struct shmid_ds{ uid_t shm_perm.uid; uid_t Shm_perm.gid; mode_t Shm_perm.mode;};
iii. using shared memory for interprocess communication
Said so much, again to the actual combat time. The following is a two unrelated process that describes how the process communicates through shared memory. One of the files shmread.c creates the shared memory and reads the information in it, and the other file shmwrite.c writes the data to the shared memory. In order to facilitate the unification of operation and data structure, the same data structure is defined for these two files, which is defined in the file shmdata.c . The written in the structure Shared_use_st as a readable or writable flag, not 0: readable, 0: writable, and text in memory.
The source code for SHMDATA.H is as follows:
#ifndef _shmdata_h_header#define _shmdata_h_header#define TEXT_SZ 2048struct shared_use_st{int written;//as a sign, Non 0: Indicates readable, 0: Indicates writable char TEXT[TEXT_SZ]; Record the text written and read}; #endif
Source file shmread.c The source code is as follows:
#include <stddef.h> #include <sys/shm.h> #include <stdio.h> #include <stdlib.h> #include < unistd.h> #include <string.h> #include "shmdata.h" int main (int argc, char **argv) {void *shm = Null;struct shared_ Use_st *shared; Point to Shmint Shmid; Shared memory identifier//create shared memory Shmid = Shmget ((key_t) 1234, sizeof (struct shared_use_st), 0666| Ipc_creat); if (Shmid = =-1) {fprintf (stderr, "Shmat failed\n"); exit (exit_failure);} Connect the shared memory to the current process's address space SHM = Shmat (shmid, 0, 0), if (SHM = = (void *)-1) {fprintf (stderr, "Shmat failed\n"); exit (Exit_failure); }printf ("\nmemory attached at%x\n", (int) SHM);//settings Shared memory shared = (struct shared_use_st*) SHM; Note: SHM is somewhat similar to the memory obtained through malloc (), so here you need to do a type cast Shared->written = 0;while (1)//Read data in Shared memory {//No process writes data to memory, there is data to read if (SHA Red->written = = 1) {printf ("you wrote:%s", Shared->text), sleep (1),///Read data, set written to make shared memory segments writable Shared->written = 0;//input End, exit loop (program) if (strncmp (Shared->text, "End", 3) = = 0) {break;}} else//Other processes are writing data, cannot read data {sleep (1);}} PutThe shared memory is detached from the current process if (SHMDT (SHM) = =-1) {fprintf (stderr, "Shmdt failed\n"); exit (exit_failure);} Delete Shared memory if (Shmctl (Shmid, ipc_rmid, 0) = =-1) {fprintf (stderr, "Shmctl (ipc_rmid) failed\n"); exit (exit_failure);} Exit (exit_success);}
The source code for the
shmwrite.c file is as follows:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys /shm.h> #include "shmdata.h" int main (int argc, char **argv) {void *shm = null;struct shared_use_st *shared = Null;char bu Ffer[bufsiz + 1]; Used to save input text int shmid;//Create shared memory Shmid = Shmget ((key_t) 1234, sizeof (struct shared_use_st), 0666| Ipc_creat); if (Shmid = =-1) {fprintf (stderr, "Shmget failed\n"); exit (exit_failure);} Connect the shared memory to the current process address space SHM = Shmat (Shmid, (void *) 0, 0), if (SHM = = (void *)-1) {fprintf (stderr, "Shmat failed\n"), Exit (EXIT_FA Ilure);} printf ("Memory attched at%x\n", (int) SHM);//set shared memory shared = (struct Shared_use_st *) shm;while (1)//write data to Shared memory {//Data not yet read Data is read, the text cannot be written to the shared memory while (Shared->written = 1) {sleep (1);p rintf ("waiting...\n");} Writes data to the shared memory printf ("Enter some text:"); fgets (buffer, bufsiz, stdin); strncpy (shared->text, buffer, TEXT_SZ);//finish writing the data , set written to make the shared memory segment readable Shared->written = 1;//input end, exit loop (program) if (strncmp (buffer, "End", 3) = = 0) {break;}} The sharedThe memory is detached from the current process if (SHMDT (SHM) = =-1) {fprintf (stderr, "Shmdt failed\n"); exit (exit_failure);} Sleep (2); exit (exit_success);}
Take a look at the results of the run:
Analysis:
1, the program Shmread create shared memory, and then connect it to its own address space. A structure Struct_use_st was used at the beginning of shared memory. There is a flag in this structure written, when other processes in the shared memory write to it, the written in shared memory is set to 0, and the program waits. When it is not 0 o'clock, indicating that no process is writing data to the shared memory, the program reads the data from the shared memory and outputs it, then resets the written in shared memory to 0, which allows it to be written to by the shmwrite process.
2, the program Shmwrite to obtain the shared memory and connect to their own address space. Check if the written in shared memory is 0, if not, indicates that the data in shared memory has not been completed, waits for the other process to read, and prompts the user to wait. If the shared memory written is 0, indicating that no other process is reading the shared memory, prompting the user for text, and setting the written in shared memory again to 1, indicating that the write is complete and that other processes can read the shared memory.
Iv. Security Discussion on the previous example
This program is not secure, and the problem occurs when multiple programs are reading and writing data to shared memory. You might think that you can change the way written is used, for example, only if the written is 0 o'clock the process can write data to the shared memory, and when a process is written not 0 o'clock to read it, and the written is added 1 operation, After reading, the operation is reduced by 1. This is a bit like the ability to read and write locks in file locks. At a glance, it seems to make sense. But this is not an atomic operation, so this practice is not possible. Imagine that when written is 0 o'clock, if there are two processes accessing shared memory at the same time, they will find that written is 0, so two processes write to it, obviously not. When written is 1 o'clock, there are two processes concurrently reading the shared memory, and when both processes are read, written becomes-1.
In order for the program to execute safely, there is a process synchronization to ensure that the operation to enter the critical section is an atomic operation. For example, you can use the semaphore described earlier to synchronize processes. Because the operation of the semaphore is atomic.
v. Advantages and disadvantages of using shared memory
1, advantages: we can see the use of shared memory for interprocess communication is really convenient, and the interface of the function is also simple, data sharing also makes the data between processes not to transmit, but directly access memory, but also speed up the efficiency of the program. At the same time, it does not require a certain parent-child relationship as the process of communicating with anonymous pipelines.
2, Disadvantage: Shared memory does not provide a mechanism for synchronization, which allows us to use shared memory for interprocess communication, often with the help of other means of synchronization between processes.
Reference:
http://blog.csdn.net/ljianhui/article/details/10253345
"Linux High Performance Server Programming"
"UNIX Network Programming _ volume 2_ interprocess communication"
Linux interprocess communication-Shared memory Shmget (), Shmat (), SHMDT (), Shmctl ()