IPC forms in addition to pipelines, FIFO, semaphores, there is a shared memory area and Message Queuing. Here the main heap shared memory is introduced.
The shared memory area is the fastest available in the IPC form. Once such a memory area is mapped to the process address space in which it is shared, the transfer of data between these processes no longer involves the kernel. Shared memory is a very efficient process communication scheme, compared with other process communication methods, it does not need to copy data and read and write memory directly. But it does not provide the synchronous access mechanism itself, which requires our own control. In Linux, as long as the shared memory segment is connected to the address space of the process, the process can access the addresses in the shared memory. In order to realize the synchronization between the process of storing and extracting data to the shared memory area, the data written by itself is prevented from being read out by itself. This is the time for the semaphore we've mentioned before.
Shared memory is a special address space created by the system, allowing unrelated processes to use this memory space, where multiple processes can use the same piece of data in memory.
The shared memory operation functions provided by the
Linux system are similar to semaphores, message queues, and the like, mainly the following:
(1) int shmget (key_t key,int shmsz,int shmflg);
The
Shmget () function allocates a new piece of shared memory. Key refers to the key value that is obtained by Ftok. SHMSZ indicates the size of the shared memory, in bytes, and the SHMFLG setting is the flag information
returns the ID of the shared memory if the Shmget () function call succeeds; otherwise returns-1.
(2) void *shmat (int shmid,const void *shmaddr, int shmflg);
The function of the
Shmat () function is to connect shared memory with the address space of a process. The
Shmid is the shared memory ID returned by the Shmget () function. SHMADDR is the storage address of the shared memory connection to the process, which is generally set to a null pointer, indicating that this work is done by the system.
If SHMADDR is 0 then this segment is connected to the first available address selected by the kernel, which is recommended for use
if SHMADDR is nonzero and no shm_rnd is specified, the segment is linked to the address referred to by addr
If SHMADDR is not 0 and specifies Shm_rnd, then this segment is linked to the address represented by SHMADDR-(addr mod ulus Shmlba). Shm_rnd means a low-boundary address multiplier, which is always 2. The equation is to take the address down to a multiple of the nearest Shmlba
Shmflg to set control options for shared memory, with two possible values: Shm_rnd (associated with shmaddr parameters) and shm_rdonly (read only). Returns a pointer to shared memory if the Shmat () function call succeeds; otherwise returns-1.
(3) int shmdt (const void *shmaddr);
The
Shmdt () function is used to disassociate a process from a shared memory region so that the current process cannot continue to access shared memory. The parameter shmaddr is a pointer returned by the Shmat () function. Returns 0 if the operation succeeds, or -1 for failure.
(4) int shmctl(int shmid, int cmd,struct shmid_ds *buf);
The Shmctl () function implements a control operation on a shared memory area.
CMD: Indicates the action to be performed, often with the following commands:
Ipc_stat: Call the Shmctl function, take the Ipc_stat command, get the size of an existing memory area
Ipc_set: Call the Shmctl function, execute the ipc_set command, set the value in an existing memory area
Ipc_rmid: Call the Shmctl function, execute the ipc_rmid command, and delete the shared memory area object.
Here is an example of a server-client communication between a semaphore and a shared memory union, where the server and client communicate based on two semaphores, and the Semaphore 1 is responsible for the server's write and client reads, while Semaphore 2 is responsible for the server's read and client writes (because of the half-duplex pipeline reason , cannot control both read and write). While the read and write information is stored in shared memory, the server writes the data into the shared memory and sends out a message to the client, and the client takes the data read in memory. And the function of the semaphore is synchronous control, according to the characteristics of the 0 blocking process, to prevent the server to write their own data to read the error occurred.
Server-side code:
Ser.cpp
#include "utili.h"intMainintargcChar*argv[]) {/ * Create a unique key value and determine if the creation is successful * /key_t key_id; key_id = Ftok (argv[1], ID);if(key_id = =-1){printf("Ftok error.\n");Exit(1); }Create a piece of shared memory of size 1024 with the key value created above. Either create or return a eexist error, the permissions are the number of users, the array, and other users can read and write. and determine if it was created successfullykey_t shm_id = Shmget (key_id,1024x768, ipc_creat| ipc_excl|0666);if(shm_id = =-1){printf("Shmget error.\n");Exit(1); }//Establish a connection in the shared memory created, the address is assigned by the system, and the connection is detected successfully Char* Addr = (Char*) Shmat (shm_id, NULL,0);if(Addr = = (Char*)-1){printf("Shmat error.\n"); Shmctl (shm_id, Ipc_rmid, NULL);Exit(1); }//re-create a new key value and determine if the creation was successfulkey_t Sem_key, sem_id; Sem_key = Ftok (argv[1], ID1);if(Sem_key = =-1){printf("sem ftok error.\n");Exit(1); }Create two semaphore sets with the key values created above and determine if the semaphore collection was created successfullysem_id = Semget (Sem_key,2, ipc_creat| ipc_excl|0666);if(sem_id = =-1){printf("Semget error.\n");Exit(1); }//Assign initial value to two semaphores 0 UnionSemun Init; Init.val =0; Semctl (sem_id,0, Setval, Init); Semctl (sem_id,1, Setval, Init);//Define two SEMBUF structures to control the number of semaphore resources structSembuf p = {0, -1,0};structSembuf v = {1,1,0}; while(1){//Server Write data "at this point the value of signal number No. 0 is 0, is in a blocking state, so it does not read the data written by itself" printf("Ser:>"); Gets (addr);//Determine if the data it writes to is quit, if(strncmp(Addr,"Quit",4) ==0) {Semop (sem_id, &v,1);//The corresponding semaphore is set with the result body v. Guarantees that the end message can be read by the client, preventing the client from waiting for the server-side dataSHMDT (addr);//Disconnecting shared memory connectionsShmctl (shm_id, Ipc_rmid, NULL);//delete shared memory Area //Delete two semaphore sets created beforeSemctl (sem_id,0, Ipc_rmid); Semctl (sem_id,1, Ipc_rmid); Break; }//If the input data section is quit, the corresponding semaphore is set with the result body v. The guarantee information can make the client readSemop (sem_id, &v,1);//server Read data "At this point the value of signal number 1th is 0, the client read operation is in a blocked state"Semop (sem_id, &p,1);//Change the value of signal number No. 0 to keep the server's read operation in a running state printf("cli:>%s\n", addr);//Compare whether the data from the client is quit, if quit, disconnect and delete the shared memory area and semaphore created before the value and exit. if(strncmp(Addr,"Quit",4) ==0) {shmdt (addr); Semctl (shm_id, Ipc_rmid, NULL); Semctl (sem_id,0, Ipc_rmid); Semctl (sem_id,1, Ipc_rmid); Break; } }return 0;}
Client program:
Cli.cpp:
#include "utili.h"intMainintargcChar* argv[]) {create an identical key value with the same path and value as the server side and determine if the creation was successfulkey_t key_id = Ftok (argv[1], ID);if(key_id = =-1){printf("Ftok error.\n");Exit(1); }//Use this key value to find the ID number of the shared memory created by the server side and determine if the lookup was successfulkey_t shm_id = Shmget (key_id,0,0);if(shm_id = =-1){printf("Shmget error.\n");Exit(1); }//Connect to shared memory and ensure successful connection creation Char*ADDR = (Char*) Shmat (Shm_id,null,0);if(Addr = = (void*)-1) {printf("Shmat error.\n");Exit(1); }//re-create the same sem_key as the server to create a semaphore setkey_t Sem_key = Ftok (argv[1],ID1);if(Sem_key = =-1) {printf("sem ftok error.\n");Exit(1); }//Find the ID number of the two semaphore sets created by the serverkey_t sem_id = Semget (Sem_key,0,0);if(sem_id = =-1) {printf("Semget error.\n");Exit(1); }///Create two SEMBUF type structure, the scalar semnum (first parameter) corresponding to the operation of P, V should be the opposite of the server side, in order to achieve synchronization structSembuf p = {1,-1,0};structSembuf v = {0,1,0}; while(1){//client read the data and determine if the data came from the server is quit, if the direct program ends for quitSemop (sem_id, &p,1);printf("ser:>%s\n", addr);if(strncmp(Addr,"Quit",4) ==0){ Break; }//The data read is not quit, the client writes the data "at this point the value of signal number 1th is 0, the client's read operation is blocked" printf("Cli:>"); Gets (addr);//If the data sent by the client is quit, the value of signal number No. 0 is added 1, and then exits the program to ensure that the server can read the data, thus disconnecting, preventing the server from waiting for the client's data if(strncmp(Addr,"Quit",4) ==0) {Semop (sem_id, &v,1); Break; }//If not quit, add the value of signal number No. 0 to 1 to keep the server's read operation runningSemop (sem_id, &v,1); }return 0;}
Header file:
Utili.h:
#pragma once#include <iostream>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/ipc.h>#include <sys/sem.h>#include <sys/shm.h>using namespace STD;#define ID 0xFF#define ID1 0xFEUnionsemun{intVal/ * value for Setval * / structSemid_ds *buf;/ * buffer for Ipc_stat & Ipc_set * / unsigned Short*Array;/ * Array for GETALL & SETALL * / structSeminfo *__buf;/ * buffer for Ipc_info * / void*__pad;};
Program Run Result:
Here is the real embodiment of the role of the signal, it can achieve synchronization mechanism, in fact, compared to the shared memory, the IPC form of the message queue itself with a synchronous form, the order will continue to collate, welcome to visit ~ ~.
UNIX Network programming: Shared Memory Area