mmap() 系统调用使得进程之间通过映射同一个普通文件实现共享内存。普
通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进
行访问,不必再调用 read() , write ()等操作。
注:实际上, mmap() 系统调用并不是完全为了用于共享内存而设计的。它
本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样
对普通文件的操作。而 Posix 或系统 V 的共享内存 IPC 则纯粹用于共享目的
,当然 mmap() 实现共享内存也是其主要应用之一。
1 、建立内存映射函数
mmap()
功能:用来将某个文件内容映射到内存中,对该内存区域的访问即是直接
对该文件内容的读写。调用成功返回映射区的内存起始地址,进程可直接
操作起始 地址为该值的有效地址 ,否则返回 -1 。
#include<unistd.h>
#include<sys/mman.h>
void *mmap(void *addr/* 指定文件应被映射 到进程空间的起始地址,一
般被指定一个空指针,此时选择起始地址的任务留给内核来完成 */
, size_t len/* 映射到调用进程地址空间的字节数,它 从被映射文件开头
offset 个字节开始算起 */
, int prot/* 指定共享内存的访问权限。可取如下几个值的或:
PROT_READ (可读) ,
PROT_WRITE (可写) ,
PROT_EXEC (可执行) ,
PROT_NONE (不可访问)。 */
, int flags/*flags 由以下几个常值指定: MAP_SHARED , MAP_PRIVATE ,
MAP_FIXED ,其中, MAP_SHARED , MAP_PRIVATE 必选其一,而 MAP_FIXED 则不推荐使用 */
, int fd/*fd 为即将映射到进程空间的文件描述字,一般由 open() 返回,
同时, fd 可以指定为 -1 ,此时须指定 flags 参数中的 MAP_ANON ,表明进 行
的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然
只能用于具有亲缘关系的进程间通信) */
, off_t offset)/* 一般设为 0 ,表示从文件头开始映射 */
2 、系统调用 mmap() 用于共享内存的两种方式
1 )、使用普通文件提供的内存映射:适用于任何进程之间; 此时,需要
打开或创建一个文件,然后再调用 mmap() ;典型调用代码如下:
fd=open(name, flag, mode);
if(fd<0)
...
2 )、使用特殊文件提供匿名内存映射:适用于具有亲缘关系的进程之间;
由于父子进程特殊的亲缘关系,在父进程中先调用 mmap() ,然后调用
fork() 。那么在调用 fork() 之后,子进程继承父进程匿名映射后的地址空
间,同样也继承 mmap() 返回的地址,这样,父子进程就可以通过映射区域
进行通信了。注意,这里不是一般的继承关系。一般来说,子进程单独维
护从父进程 继承下来的一些变量。而 mmap() 返回的地址,却由父子进程共同维护。
对于具有亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映
射的方式。此时,不必指定具体的文件,只要设置相应的标志即可
3 、解除内存映射函数
munmap
用来取消参数 start 所指向的内存起始地址,成功返回 0 ,失败返回 -1
#include<unistd.h>
#include<sys/mman.h>