存储映射I/O
将文件从磁盘中映射到内存空间进行操作,会使文件运行更加迅速
存储映射I/O是一种基于内存区域的高级I/O操作,它将磁盘文件与进程地址空间中的一个内存区域相映射。当从这段内存中读数据时,就相当于读磁盘文件中的数据,将数据写入这段内存时,则相当于将数据直接写入磁盘文件。这样就可以在不使用基本I/O操作函数read和write的情况下执行I/O操作。
函数
进行映射
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 参数:
addr:内存映射起始地址 通常设为NULL,由系统分配
length:共享内存映射的大小,一般是磁盘文件的长度,单位字节
port:共享内存访问权限,PROT_READ,PROT_WRITE,PROT_READ|PROT_WRITE,
flags:标注共享属性:MPA_FIXED(add具体指定后,禁止创建),MAP_PRIVATE(只读映射),MAP_SHARED(读写自由)
fd:用于创建共享映射区的那个文件的文件描述符
offset:偏移位置,需要4k的整数倍
取消映射
int munmap(void *addr, size_t length);
Addr:需要撤销内存映射区的首地址
length:内存映射区的长度,单位字节
将初始文件赋予大小
ftruncate(fd, 10);
Fd:文件描述符
10:被赋予的大小
mmap注意事项:
思考:
- 可以open的时候O_CREAT一个新文件来创建映射区吗?文件大小为0,
==不行
- 如果open时O_RDONLY,mmap时PROT参数指定PROT_READ|PROT_WRITE会怎样?
==open只读,flags为MAP_SHARED 时,则prot也必须为只读,否则提示权限不足
== ==open只读,flags为MAP_PRIVATE 时,则prot读写,可以正常读出内容
- 文件描述符先关闭,对mmap映射有没有影响?
==mmap成功之后,可以关闭文件描述符
- 如果文件偏移量为1000会怎样?
==报错
- 对p=mmap()越界操作会怎样?
==属于越界访问,不安全
- 如果p++,munmap, 可否成功?
==报错
- mmap什么情况下会调用失败?
==文件大小为0时
- 如果不检测mmap的返回值,会怎样?
==会出现段错误
总结:
- 创建映射区的过程中,隐含着一次对映射文件的读操作
- 当MAP_SHARED 时,要求:映射区的权限应<=文件打开的权限(出于对映射区的保护)。而 MAP_PRIVATE则无所谓,因为mmap中的权限是对内存的限制。
- 映射区的释放与文件关闭无关。只要映射建立成功,文件可以立即关闭。
- 特别注意, 当映射文件大小为0时,不能创建映射区。所以:用于映射的文件必须要有实际大小!! mmap使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。如,400 字节大小的文 件,在建立映射区时offset 4096字节,则会报出总线错。
- munmap 传入的地址一定是mmap的返回地址。坚决杜绝指针++操作。
- 如果文件偏移量必须为4K的整数倍。
- mmap 创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。
匿名映射
int*p=
mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1, 0};
需注意的是,MAP_ ANONYMOUS和MAP_ ANON 这两个宏是Linux 操作系统特有的宏。在类Unix系统 中如无宏定义。可使用如下两步来完成匿名映射区的建立。
fd= open("/dev/zero", O_RDWR);
p= mmap(NULL, size, PROT_READ|PROT_WRITE, MMAP_SHARED, fd, 0);
总结:适用于有血缘关系的进程之间进行通信。