The memory between the different processes is independent of each other, there is no way to directly manipulate each other's data, while the shared memory is provided by the operating system memory mapping mechanism, so that the different processes of a single address space mapped to the same virtual memory area, so that different processes can operate to a common block of memory. Shared memory is the most efficient inter-process communication mechanism because the data does not need to be replicated between the kernel and the program.
Shared memory is used by the system-provided mmap function, which can map a file to a region of virtual memory, the program uses pointers to refer to this area, the operation of this memory area will be written back to the file, the function prototype is as follows:
void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
- The parameter fd is the file descriptor that will be mapped to the process space, usually returned by open (), and the FD can be specified as-1, at which point the Map_anon in the flags parameter must be specified, indicating that the anonymous mapping is done (not involving the specific file name, avoiding the creation and opening of the file, Obviously, it can only be used for inter-process communication with affinity.
- Len is the number of bytes mapped to the calling process address space, starting at offset bytes at the beginning of the mapped file.
- The prot parameter specifies the access rights for shared memory. The following values may be desirable or: prot_read (readable), prot_write (writable), prot_exec (executable), Prot_none (inaccessible).
- Flags are specified by the following constant values: map_shared, Map_private, map_fixed. Among them, map_shared,map_private must choose one, and map_fixed is not recommended. If specified as map_shared, modifications made to the mapped memory also affect the file. If it is map_private, modifications made to the mapped memory are only visible to the process and have no effect on the file.
- The offset parameter is typically set to 0, which indicates that the mapping starts from the file header.
- The addr parameter specifies that the file should be mapped to the start address of the process space and is typically assigned a null pointer, at which point the task of selecting the start address is left to the kernel. The return value of the function is the address that the last file maps to the process space, and the process can manipulate the starting address directly to the valid address of the value.
Incidentally, let's introduce the Shm_open and Shm_unlink two functions:
Shm_open () function
Function: Open or create a shared memory area
Header files: #include <sys/mman.h>
Function prototype: int shm_open (const char *name,int oflag,mode_t mode);
Return value: Successfully returned 0, error returned-1
Parameters:
Name of the shared memory area
Oflag flag bit
Mode permission bit
Parameter interpretation: The Oflag parameter must contain the o_rdonly and O_RDWR flags, and you can specify the following flag: The O_CREAT,O_EXCL or O_trunc.mode parameter specifies the permission bit,
It specifies the O_CREAT flag that is used under the premise. The return value of Shm_open is an integer descriptor, which is then used as the fifth parameter of the mmap.
Shm_unlink () function
Function: Delete a shared memory area
Header files: #include <sys/mman.h>
Function prototype: int shm_unlink (const char *name);
Parameter: Name of the shared memory area
Return value: Successfully returned 0, error returned-1
The Shm_unlink function removes the name of a shared memory area object, and deleting a name only prevents subsequent Open,mq_open or Sem_open calls from succeeding.
You can refer to this article to learn more about mmap functions such as: http://www.cnblogs.com/polestar/archive/2012/04/23/2466022.html
You can implement mmap in C by using the Golang call Cgo method. The experiment consists of reading and writing two programs so that we can observe that the read process can read to the writing process to write the shared memory information.
Shm_writer.go code Example:
<pre class= "BRUSH:CPP; Toolbar:true; Auto-links:false; "Style=" Box-sizing:border-box; Overflow:auto; Font-family:menlo, Monaco, Consolas, "Courier New", monospace; font-size:14px; Display:block; padding:10px; margin:0px 0px 10.5px; line-height:1.42857; Word-break:break-all; Word-wrap:break-word; Color:rgb (51, 51, 51); Background-color:rgb (245, 245, 245); BORDER:1PX Solid RGB (204, 204, 204); border-radius:0px; Font-style:normal; Font-variant-ligatures:normal; Font-variant-caps:normal; font-weight:400; Letter-spacing:normal; Orphans:2; Text-align:left; text-indent:0px; Text-transform:none; Widows:2; word-spacing:0px; -webkit-text-stroke-width:0px; text-decoration-style:initial; text-decoration-color:initial; " >package Main
/*
CGO Linux ldflags:-LRT
Include <fcntl.h>
Include <unistd.h>
Include <sys/mman.h>
Define File_mode (S_irusr | S_IWUSR | S_irgrp | S_iroth)
int my_shm_new (char *name) {
Shm_unlink (name);
Return Shm_open (name, o_rdwr| O_creat| O_EXCL, File_mode);
}
*/
Import "C"
Import (
"FMT"
"Unsafe"
)
Const SHM_NAME = "MY_SHM"
Const SHM_SIZE = 4 * 1000 * 1000 * 1000
Type MyData struct {
Col1 int
Col2 int
Col3 int
}
Func Main () {
FD, Err: = C.my_shm_new (c.cstring (shm_name))
If err! = Nil {
Fmt. PRINTLN (ERR)
Return
}
C.ftruncate(fd, SHM_SIZE)ptr, err := C.mmap(nil, SHM_SIZE, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, fd, 0)if err != nil { fmt.Println(err) return}C.close(fd)data := (*MyData)(unsafe.Pointer(ptr))data.Col1 = 100data.Col2 = 876data.Col3 = 8021
}</pre>
Shm_reader.go code Example:
<pre class= "BRUSH:CPP; Toolbar:true; Auto-links:false; "Style=" Box-sizing:border-box; Overflow:auto; Font-family:menlo, Monaco, Consolas, "Courier New", monospace; font-size:14px; Display:block; padding:10px; margin:0px 0px 10.5px; line-height:1.42857; Word-break:break-all; Word-wrap:break-word; Color:rgb (51, 51, 51); Background-color:rgb (245, 245, 245); BORDER:1PX Solid RGB (204, 204, 204); border-radius:0px; Font-style:normal; Font-variant-ligatures:normal; Font-variant-caps:normal; font-weight:400; Letter-spacing:normal; Orphans:2; Text-align:left; text-indent:0px; Text-transform:none; Widows:2; word-spacing:0px; -webkit-text-stroke-width:0px; text-decoration-style:initial; text-decoration-color:initial; " >package Main
/*
CGO Linux ldflags:-LRT
Include <fcntl.h>
Include <unistd.h>
Include <sys/mman.h>
Define File_mode (S_irusr | S_IWUSR | S_irgrp | S_iroth)
int My_shm_open (char *name) {
Return Shm_open (name, O_RDWR, File_mode);
}
*/
Import "C"
Import (
"FMT"
"Unsafe"
)
Const SHM_NAME = "MY_SHM"
Const SHM_SIZE = 4 * 1000 * 1000 * 1000
Type MyData struct {
Col1 int
Col2 int
Col3 int
}
Func Main () {
FD, Err: = C.my_shm_open (c.cstring (shm_name))
If err! = Nil {
Fmt. PRINTLN (ERR)
Return
}
ptr, err := C.mmap(nil, SHM_SIZE, C.PROT_READ|C.PROT_WRITE, C.MAP_SHARED, fd, 0)if err != nil { fmt.Println(err) return}C.close(fd)data := (*MyData)(unsafe.Pointer(ptr))fmt.Println(data)
}</pre>
The above program maps a 4G of virtual memory to prove that Mmap does not actually consume 4G of memory, but rather uses virtual memory. Shm_writer the shared memory is created, a struct is written to the memory area, and Shm_reader reads a struct.
The above code also uses a CGO technique, such as shm_open and mmap function in error will return errno, if we use the multiple return value syntax in Go, CGO will own the error code into error message, very convenient function.