Http://www.cnblogs.com/dubingsky/archive/2009/06/18/1505841.html
One, what is the shared memory area
The shared memory area is the fastest available form of IPC. It allows multiple unrelated processes to access the same part of the logical memory. Shared memory is a highly efficient solution if you need to transfer data between two running processes. Once such a memory area is mapped to the address space of the process that shares it, the transfer of these inter-process data is no longer involved in the kernel. This can reduce system call time and improve program efficiency.
Shared memory is a special address range created by the IPC for a process that will appear in the process's address space. Other processes can "connect" the same segment of shared memory to their own address space. All processes have access to the addresses in shared memory. If a process writes data to this shared memory, the changes are immediately visible to other processes that have access to the same section of shared memory.
Note that the shared memory itself does not provide any synchronization functionality. That is, before the first process finishes writing on shared memory, there is no automatic function to prevent the second process from starting to read it. The problem of access synchronization for shared memory must be the responsibility of the programmer. Optional synchronization methods include mutual exclusion lock, conditional variable, read-write lock, record lock, Semaphore.
Second, mmap
We'll introduce the following functions before sharing the memory.
The MMAP function maps a file or a POSIX shared memory area object to the address space of the calling process. There are three purposes to use this function:
1. Use normal files to provide memory mapped I/O
2. Use special files to provide anonymous memory mappings.
3. Use Shm_open to provide POSIX shared memory areas between unrelated processes.
1.
Name:: |
Mmap |
Function: |
Mapping I/O files to a storage area |
Header file: |
#include <sys/mman.h> |
Function prototype: |
void *mmap (void *addr,size_t len,int prot,int flag,int off); |
Parameters: |
Addr point to the starting address of the mapping store Len-Mapped bytes Prot protection requirements for mapped storage areas Flag Flag Sign Bit Filedes the descriptor of the file to be mapped Off to map the starting offset of a byte in a file |
return value: |
If successful, return the starting address of the mapping area and return map_failed if an error occurs |
The addr parameter is used to specify the starting address of the mapping store. It is usually set to NULL, which means that the system selects the starting address of the mapping area.
Filedes refers to the descriptor of the file to be mapped. Before mapping the file to an address space, open the file first. Len is the number of bytes mapped.
Off is the starting offset to map the byte in the file. It is usually set to 0.
The prot parameter describes the protection requirements for the mapped store. You can specify the prot parameter as Prot_none, or prot_read (the mapping area is readable), prot_write (the mapping area is writable), prot_exec (the mapping area can perform) any combination of bitwise OR, or prot_none (the map area is inaccessible). Protection requirements for the specified mapping store cannot exceed file open mode access.
The flag parameter affects multiple properties of the mapping area:
Map_fixed return value must be equal to addr. This flag is discouraged because it is not conducive to portability.
Map_shared This flag describes the configuration of the storage operations performed by this process on the mapping area. This flag specifies that the storage operation modifies the mapping file.
Map_private This flag causes a private copy of the mapping file to be established for the mapping area. All subsequent references to the map area refer to the copy instead of the original file.
Note that you must specify one of the map_fixed or map_private flags, specifying that the former is an operation on the storage mapping file itself, and that the latter is operating on its copy.
The FD parameter can be closed after the MMAP is successfully returned. This operation has no effect on the mapping relationship established by Mmap. To delete a mapping relationship from the address space of a process, we call Munmap.
2.
Name:: |
Munmap |
Function: |
Releasing Storage mappings |
Header file: |
#include <sys/mman.h> |
Function prototype: |
int Munmap (caddr_t addr,size_t len); |
Parameters: |
Addr point to the starting address of the mapping store Len-Mapped bytes |
return value: |
If successful, return 0, if error, return-1 |
Where the addr parameter is the address returned by Mmap, Len is the size of the map area. Access to these addresses again causes a SIGSEGV signal to be generated to the calling process.
If the mapped area is mapped using the MAP_PRIVATE flag, the changes made to it by the calling process are discarded.
The kernel's virtual storage algorithm keeps the memory-mapped file (typically on the hard disk) synchronized with the memory-mapped area (in memory) (provided it is a map_shared memory area). This means that if we modify the contents of a location in the memory mapped to a file, the kernel will update the file accordingly at a later time. However, sometimes we want to make sure that the contents of the file on the hard disk match the contents of the file in the memory-mapped area, and call Msync to perform this synchronization.
3.
Name:: |
Msync |
Function: |
Synchronizing files to Storage |
Header file: |
#include <sys/mman.h> |
Function prototype: |
int Msync (void *addr,size_t len,int flags); |
Parameters: |
Addr point to the starting address of the mapping store Len-Mapped bytes Prot Flags |
return value: |
If successful, return 0, if error, return-1 |
where the addr and Len parameters typically refer to an entire memory-mapped area in memory, but you can also specify a subset of that memory area. The flags parameter is Ms_async (performing asynchronous writes), Ms_sync (performing synchronous writes), Ms_invalidate (making the data of the cache effective). One must be specified in both Ms_async and Ms_sync, but not all. The difference is that once a write has been queued by the kernel, Ms_async returns, and Ms_sync does not return until the write operation is complete. If Ms_invalidate is also specified, all in-memory copies of file data that are inconsistent with their final copy are invalidated. Subsequent references will obtain data from the file.
4.
Name:: |
memcpy |
Function: |
Copy Map Store |
Header file: |
#include <string.h> |
Function prototype: |
void *memcpy (void *dest,const void *src,size_t n); |
Parameters: |
Dest the mapped store to be replicated The mapped store after SRC replication n the size of the mapped store to be replicated |
return value: |
Returns the first address of the Dest |
memcpy copies n bytes from dest to SRC.
Here is the CP command that uses the MMAP function to insinuate I/O implementations.
/*mycp.c*/ #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> int main (int argc,char *argv[]) { int fdin,fdout; void *arc,dst; struct stat statbuf; if (argc!=3) { printf ("Please input two file!\n"); Exit (1); } if ((Fdin=open (argv[1],o_rdonly)) <0)/* Open the original file * * * Perror (argv[1]); if (Fdout=open (argv[2],o_rdwr| O_creat| O_TRUNC)/* <0) * * Create and open the target file * * Perror (argv[2]); if (Fstat (FDIN,&STATBUF) <0)/* Get File size information * * printf ("Fstat error"); if (Lseek (fdout,statbuf.st_size-1,seek_set) ==-1)/* Initialize OUTPUT mapping Store * * printf ("Lseek error"); if (Write (Fdout, "1")!=1) printf ("Write error"); if ((Src=mmap (0,statbuf.st_size,prot_read,map_shared,fdin,0)) ==map_failed) /* Map the original file to the input mapping store * * printf ("Mmap error"); if (Dst=mmap (0,statbuf.st_size,prot_read| prot_write,map_shared,fdout,0))/* Map target file to the output mapping store/* ==map_failed printf ("Mmap error"); memcpy (dst,src,statbuf.st_size)///Copy Map store/* Munmap (src,statbuf.st_size); /* Unlock Input mapping * * Munmap (dst,statbuf.st_size); /* Unlock Output Map * * Close (Fdin); Close (fdout); } |
The following are the results of the operation:
#cc –o MYCP mycp.c
#./mycp test1 Test2
three, POSIX shared memory functions
The POSIX shared memory area involves two steps:
1, specify a name parameter call Shm_open to create a new shared memory area object or open a shared memory area object that exists.
2. Call Mmap to map this shared memory area to the address space of the calling process. The name parameter passed to the Shm_open is then used by any other process that you want to share the memory area.
5.
Name:: |
Shm_open |
Function: |
Open or create a shared memory area |
Header file: |
#include <sys/mman.h> |
Function prototype: |
int Shm_open (const char *name,int oflag,mode_t mode); |
Parameters: |
Name of the shared memory area Cflag sign Bit Mode permission bit |
return value: |
Successfully returned 0, error return-1 |
The Oflag parameter must contain o_rdonly and O_RDWR flags, and you can specify the following flags: O_CREAT,O_EXCL or O_trunc.
The mode parameter specifies the permission bit, which specifies the O_CREAT flag to use.
The return value of the Shm_open is an integer descriptor, which is then used as the fifth parameter of the mmap.
6.
Name:: |
Shm_unlink |
Function: |
Delete a shared memory area |
Header file: |
#include <sys/mman.h> |
Function prototype: |
int Shm_unlink (const char *name); |
Parameters: |
Name of the shared memory area |
return value: |
Successfully returned 0, error return-1 |
The Shm_unlink function deletes the name of a shared memory area object and deletes a name only to prevent subsequent open,mq_open or Sem_open calls from succeeding.
Here is an example of creating a shared memory area:
/*SHM_OPEN.C Create shared memory Area * * #include <sys/mman.h> #include <stdio.h> #include <fcntl.h> int main (int argc,char **argv) { int shm_id; if (argc!=2) { printf ("Usage:shm_open <pathname>\n"); Exit (1); } Shm_id=shm_open (argv[1],o_rdwr| o_creat,0644); printf ("shmid:%d\n", shm_id); Shm_unlink (argv[1]); } |
Here is the result of the run, note that we are going to add "-LRT" parameters to the compiler.