Reprint Please specify the Source: http://blog.csdn.net/suool/article/details/38515863
shared memory can be described as a mapping of an area ( segment) of memory that can be shared by more processes. This is the fastest form of the IPC mechanism because it does not require intermediate links, but instead maps the information directly from a memory segment to the address space of the calling process. A segment can be created directly by a process, which can then be read and written by as many processes as possible. However, once the memory is shared, access to shared memory needs to be synchronized by other IPC mechanisms, such as semaphores. Like all system V IPC objects, Linux access to shared memory is controlled by checking access keys and access permissions.
shared spatial data structures
<bits/shm.h>/* data type of the number of processes connected to the shared memory area */typedef unsigned long int shmatt_t;struct shmid_ds{ struct ipc_perm shm_ Perm; /* Operation permission struct */ size_t Shm_segsz; /* Maximum number of bytes shared bucket */ __time_t shm_atime; /* Time of last Shmat () */ __time_t shm_dtime; /* Time of last SHMDT () */ __time_t shm_ctime; /* Time of last change by SHMCTL () */ __pid_t shm_cpid; /* PID of Creator */ __pid_t shm_lpid; /* PID of last SHMOP */ shmatt_t shm_nattch; /* Number of processes connected to the shared memory Area *///reserved Field # if __wordsize = = unsigned long int __unused1;unsigned long int __unused2;unsigned long int __unused3; #endif unsigned long int __unused4; unsigned long int __unused5;};
Two processes need to establish a connection between the process address space and the shared memory space before using this space, that is, to hang the shared memory space in the process.
While using shared memory for data access, to avoid errors such as read intersections, it is often necessary to use a two-dollar semaphore to synchronize two processes to achieve read operations on shared memory.
There are also certain system limitations for shared memory:
#include <bits/shm.h>struct shminfo{ unsigned long int shmmax;//The maximum number of bytes in a shared memory area unsigned long int shmmin;//The minimum number of bytes in a shared memory area unsigned long int shmmni;//The maximum number of shared memory area objects in the system range unsigned long int shmseg;// The maximum number of shared memory areas connected per process unsigned long int shmall;//The maximum pages of the system-wide shared memory area unsigned long int __unused1; unsigned long int __unused2; unsigned long int __unused3; unsigned long int __unused4;};
InLinuxunderShmctlYou can specify theIpc_infoto get the system-wide limits shown in the structure above. In theLinux, the specific limit value can beSysctlto view, as follows:
[Email protected] program]# Sysctl-a | grep Shm...kernel.shmmni = maximum number of shared memory area objects in 4096//system range Kernel.shmall = 4294967296//System-wide maximum pages of shared memory Area Kernel.shmmax = 68719476736//The maximum number of bytes in a shared memory area
In general, there is no need toSystem Vthe system of the shared memory area restricts process modifications, because the basic can meet the application requirements, if you want to modify the kernel limits within the system scope,LinuxThe following can be modified by/etc/sysctl.confKernel parameter configuration file, and then mateSysctlcommand to set the kernel parameters. For example, the following example:
[[Email protected] program] #echo kernel.shmmni= (>>/etc/sysctl.conf[[email protected) program] #sysctl-p[[ Email protected] program] #sysctl-a |grep Shmkernel.shmmni = 1000kernel.shmall = 4294967296kernel.shmmax = 68719476736
process of shared memory
A page fault occurs when a process accesses shared virtual memory for the first time. At this point, Linux finds the VM_AREA_STRUCT structure that describes the memory, which contains the address of the handler that is used to handle this shared virtual memory segment. Shared memory page exception handling code searches the Shmid_ds Page table Entry table to see if there is a table entry for the shared virtual memory. If not, the system assigns a physical page and establishes a page table entry that joins the SHMID_DS structure and also adds it to the page table of the process. This means that when a process tries to access this page of memory, there will be a fault, and the page exception handling code of the shared memory will give the process the newly created physical pages. Thus, the first process's access to shared memory causes a new physical page to be created, while the other process's access to shared memory causes the page to be added to their address space.
When a process no longer shares its virtual memory, a system call is used to remove the shared segment from its own virtual address area and update the Process page table. When the last process frees the shared segment, the system frees the physical page assigned to the shared segment.
When shared virtual memory is not locked to physical memory, shared memory may also be swapped into the swap area.
creation and opening of the System V shared memory Area
The following is an interface to the Shmget function for creating shared memory and a description:
#include <sys/shm.h>int shmget (key_t key, size_t size, int shmflg); The shared memory identifier was returned successfully, and the failure returned-1
The Shmget function is used to create or open a shared memory area object, and shmget a successful call returns an identifier for the shared memory area for use by other shared memory area operations functions.
key: Used to create a shared memory area, this is discussed in the previous system IPC creation, the system IPC has a key, as an external identifier of the IPC, and the descriptor returned after the creation succeeds as the internal identifier of the IPC. The main purpose of key is to enable different processes to converge on the same IPC. Key specifically says there are three ways to generate:
- A value that is agreed by a different process;
- By calling the Ftok () function with the same pathname and project ID, a key is generated;
- It can also be set to Ipc_private, which creates a new, unique IPC object, and then passes the returned descriptor in some way to other processes;
Size: Specifies how large the shared memory area is to be created, in bytes. If the actual operation is to create a shared memory area, you must specify a value other than 0, and if the actual operation is to access an existing shared memory area, then size should be 0.
SHMFLG: Specifies the flag and read-write permission to create or open Message Queuing (the mode member in Ipc_perm). We know that the system V IPC defines its own operation flags and permission setting flags, which are passed by this parameter, which differs from the open function, and the third parameter of the Open function is used to pass the permission flags of the file. The operating flags of the System V IPC include: Ipc_creat,ipc_excl. Read and Write permissions such as:
Figure 1 Read and Write permission flags for the System v shared memory area
when the System v Shared memory area is created, the size memory area is initialized to 0, unlike POSIX shared memory, where the POSIX standard does not specify the initial content of the newly created POSIX shared memory area .
Connection and disconnection of the System V shared memory Area
After creating or opening a shared memory area object through SHMCTL, the shared memory area is not mapped to the address space of the calling process, so the shared memory area cannot be accessed and needs to be passed through the shmat function. The shared memory area is connected to the calling process's address space for access, and when the process completes its access to the shared memory area, it can call shmdt to disconnect the shared memory area and, of course, automatically disconnect all connected shared memory areas when the process ends. The following is an interface to the Shmat and SHMDT functions and a description:
#include <sys/shm.h>void *shmat (int shmid, const void *shmaddr, int shmflg); The start address of the mapped area is returned successfully, and the failure returns -1int SHMDT (const void *shmaddr); Successful return 0, failure return-1
Shmat is used to connect a shared memory area to the address space of the calling process.
Shmid: The identifier of the open System V shared memory object;
shmaddr and the SHMFLG parameters together determine the specific address of the shared memory area to the calling process, as follows:
- shmaddr null pointer : The address of the connection is determined by the system kernel, This is the recommended method, with portability .
- shmaddr: At this time also according to SHMFLG parameter specified shm_rnd flag:
- not specified shm_rnd : The shared memory area is connected to the address specified by the shmaddr of the calling process;
- Specify shm_rnd : Shared memory area connected to shmaddr The address specified is rounded down The location of the span style= "Font-family:times New Roman" >shmlba .
SHMFLG: In addition to the above mentioned shm_rnd , there can be specified shm_rdonly Flag, limited to read-only access. In general, this flag is set to 0.
SHMDT is used to disconnect a shared memory area from within the process, and when a process terminates, all of the shared memory areas it connects to are automatically disconnected.
control operation of the System v Shared memory Area
The Shmctl function can perform various control operations on the shared memory area, following the interface of the SHMCTL function and the description:
#include <sys/shm.h>int shmctl (int shmid, int cmd, struct shmid_ds *buf); Successful return 0, failure return-1
shmid: identifier of the shared memory area.
cmd : command for the shared memory area control operation, OPEN&NBSP;GROUP&NBSP; Span style= "font-family: Arial" > sus defines three action commands:
- Ipc_set: Set the Operation permission field for the shared memory areaby the buf specified by thethird parameter :shm_perm.uid,shm_ Perm.gid and shm_perm.mode. This command can only be performed by the following processes: Valid user ID equals shm_perm.uid or shm_perm.cuid , as well as processes with superuser privileges.
- Ipc_stat: Gets the SHMID_DS structure of the shared memory area , which is stored in the third parameter passed in.
- ipc_rmid: Remove the shared memory area from the system kernel. Because each shared memory area has a count of connection data, the shared memory area is not actually deleted unless the last process connecting to the shared memory area is disconnected or terminated. this and the other system v IPC system v Message queue deletion is very different, but and posix &NBSP;IPC xxx_unlink delete operation very familiar . After the command is called, the shared memory area identifier cannot continue to be connected. This command can only be performed by the following processes: Valid user id Span style= "Font-family:times New Roman" >shm_perm.uid or shm_perm.cuid
Other control commands are also defined in Linux, such as:ipc_info,shm_info,shm_lock , Shm_unlock and so on, can be referenced in detail Linux Manual.
Here's how to createSystem Vthe test code that shares the memory area and views its properties:
#include <iostream> #include <cstring> #include <errno.h> #include <unistd.h> #include < Fcntl.h> #include <sys/shm.h>using namespace std; #define PATH_NAME "/tmp/shm" int main () {int fd; if (fd = open (Path_name, O_creat, 0666)) < 0) {cout<< "Open file" <<PATH_NAME<< "failed."; Cout<<strerror (errno) <<endl; return-1; } close (FD); key_t key = Ftok (path_name, 0); int shmid; if (Shmid = Shmget (key, sizeof (int), ipc_creat | 0666)) < 0) {cout<< "Shmget failed ..." <<strerro R (errno) <<endl; return-1; } Shmid_ds Shminfo; Shmctl (Shmid, Ipc_stat, &shminfo); cout<< "SHM key:0x" <
Shared Memory Sample appThis sample program implements a non-affinity between two processes through shared memory communication, while using semaphores to guarantee the read and write synchronization of two processes: that is, when the sender writes shared memory, the receiver cannot read the memory area, and vice versa.
In code, using shared memory to pass data, the basic idea of using semaphores to synchronize Read and write ends is as follows:
- First, the semaphore is initially set to 0, indicating that no data is written and unreadable.
- The sending side writes the data to the shared memory when the semaphore bit 0, and blocks the reading process, after the write completes, sets the semaphore bit 1, at this time can read the data, cannot write the data.
- The receiving end reads out the data of the memory area and blocks the writing end when the semaphore bit is 1, and after the readout is completed, the value bit of the semaphore is set to 0, which means that the data can be written again.
Here are the compilation and run results:
Send side:
Receiving end
The code is as follows:
Send:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include < sys/shm.h> #include <sys/ipc.h> #include <sys/sem.h> #include <string.h>int main (int Argc,char * Argv[]) {int running=1; int Shid; int semid; int value; Char *sharem=null; struct SEMBUF sem_b; Sem_b.sem_num = 0; SEM_B.SEM_FLG = Sem_undo; if ((Semid=semget (key_t) 123456,1,0666| ipc_creat) ==-1)//create semaphore {perror ("Semget"); Exit (Exit_failure); } if (Semctl (semid, 0, setval, 0) = =-1)//Set initial value bit 0 {printf ("SEM init error"); if (Semctl (semid,0,ipc_rmid,0)!=0) {perror ("Semctl"); Exit (Exit_failure); } exit (Exit_failure); } shid=shmget (key_t) 654321, (size_t) 2048,0600| Ipc_creat); Create shared memory (read ID) if (shid==-1) {perror ("Shmget"); Exit (Exit_failure); } sharem=shmat (shid,null,0); Mount shared memory to process if (sharem==nuLL) {perror ("Shmat"); Exit (Exit_failure); } while (running) {if ((Value=semctl (semid, 0, Getval) ==0)//read as 0 o'clock {printf ("Write D ATA operate\n "); Writable printf ("Please input something:"); scanf ("%s", Sharem); Read to Shared memory Sem_b.sem_op = 1; Set the semaphore plus an action if (Semop (Semid, &sem_b, 1) = =-1)//Perform an additional operation {fprintf (stderr, "s Emaphore_p failed\n "); Exit (Exit_failure); }} if (strcmp (Sharem, "end") ==0)//Enter end running--; }SHMDT (Sharem); Unload memory return 0;}
Accept:
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include < string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h>int main (int Argc,char * Argv[]) {int running=1; Char *shm_p=null; int shmid; int semid; int value; struct SEMBUF sem_b; Sem_b.sem_num = 0; SEM_B.SEM_FLG = Sem_undo; if ((Semid=semget (key_t) 123456,1,0666| Ipc_creat) ==-1) {perror ("Semget"); Exit (Exit_failure); } shmid=shmget (key_t) 654321, (size_t) 2048,0600| Ipc_creat); if (shmid==-1) {perror ("Shmget"); Exit (Exit_failure); } shm_p=shmat (shmid,null,0); Hook up if (shm_p==null) {perror ("Shmat"); Exit (Exit_failure); } while (running) {if ((Value=semctl (semid, 0, Getval) ==1) {printf ("Read Data operate\n" ); Sem_b.sem_op =-1; Minus one if (Semop (Semid, &sem_b, 1) = =-1) {fprintf (stderr, "semaphore_p failed\n"); Exit (Exit_failure); } printf ("%s\n", shm_p); } if (strcmp (shm_p, "end") ==0) running--; } shmdt (shm_p); Uninstall if (Shmctl (shmid,ipc_rmid,0)!=0)//delete shared memory {perror ("Shmctl"); Exit (Exit_failure); } if (Semctl (semid,0,ipc_rmid,0)!=0)//delete semaphore {perror ("Semctl"); Exit (Exit_failure); } return 0;}
Reprint Please specify the Source: http://blog.csdn.net/suool/article/details/38515863