mmap系统调用使用-学习笔记

1. mmap函数参数说明

头文件:#include <unistd.h> #include <sys/mman.h>

void *mmap(void *adrr,size_t length,int prot,int flags,int fd,off_t offset);

返回:成功:返回创建的映射区首地址;失败:MAP_FAILED

参数:
addr: 建立映射区的首地址,由Linux内核指定。使用时,直接传递NULL
length:欲创建映射区的大小
prot: 映射区权限PROT_READPROT_WRITEPROT_READ|PROT_WRITE
flags: 标志位参数(常用于设定更新物理区域、设置共享、创建匿名映射区)
MAP_SHARED: 会将映射区所做的操作反映到物理设备(磁盘)上。
MAP_PRIVATE: 映射区所做的修改不会反映到物理设备。
fd: 用来建立映射区的文件描述符
offset: 映射文件的偏移(4k的整数倍)

2. mmap父子进程通信

父子等有血缘关系的进程之间也可以通过mmap建立的映射区来完成数据通信。但相应的要在创建映射区的时候指定对应的标志位参数flags:
MAP_PRIVATE:(私有映射)父子进程各自独占映射区;
MAP SHARED:(共享映射)父子进程共享映射区.

问:父进程创建映射区,然后fok子进程,子进程修改映射区内容,而后,父进程读取映射区内容,查验是否共享。

答:父子进程共享:
1.打开的文件   
2.mmap建立的映射区(但必须要使用MAP_SHARED)

3. 匿名映射

通过使用我们发现,使用映射区来完成文件读写操作十分方便,父子进程间通信也较容易。但缺陷是,每次创建映射区一定要依赖一个文件才能实现。通常为了建立映射区要open一个temp文件,创建好了再unlink、close掉,比较麻烦。可以直接使用匿名映射来代替。其实Linux系统给我们提供了创建匿名映射区的方法,无需依赖一个文件即可创建映射区。同样需要借助标志位参数flags来指定。
使用MAP_ANONYMOUS(或MAP_ANON),如:

int *p mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED MAP_ANONYMOUS, -1, 0);

"4"随意举例,该位置表大小,可依实际需要填写。

需注意的是,MAP_ANONYMOUS和MAP_ANON这两个宏是Linux操作系统特有的宏。在类Unix系统中如无该宏定义,可使用如下两步来完成匿名映射区的建立。

fd = open("/dev/zero",O RDWR);
p = mmap(NULL,size,PROT_READ |PROT_WRITE,MMAP_SHARED,fd,0);

4. mmap基本使用示例

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>

int test01() {
       int len = 0;
       int ret = 0;
       int fd = open("mytest.txt", O_CREAT | O_RDWR, 0644);
       if (fd < 0) {
              printf("open failed\n");
              exit(1);
       }
       len = ftruncate(fd, 4);
       if (len == -1) {
              printf("ftruncate error!\n");
              exit(1);
       }
       p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
       if (p == MAP_FAILED) {
              printf("mmap error!\n");
              exit(1);
       }
       strcpy(p, "abc");
       ret = munmap(p, 4);
       if (ret == -1) {
              printf("munmap failed!\n");
              exit(1);
       }
       close(fd);
       return 0;
}

5. mmap使用常见问题

1. Q:可以open的时候O_CREAT一个新文件来创建映射区吗?
A:可以,但不能创建大小为0(mmap第二个参数)的映射区,使用ftruncate指定文件大小。

2. Q:如果p++,munmap可否成功?
A:失败,mmap和munmap的地址必须一致。

3. Q:如果open时O RDONLY,mmap时PROT参数指定PROT READ|PROT WRITE会怎样?
A:失败,permission denied。创建映射区的必须小于等于打开文件的权限;创建映射区隐藏的读文件操作。所以mmap参数必须要有读权限。

4. Q:如果文件偏移量为1000会怎样?
A:最后一个参数offset必须是0或者4K的整数倍 ,mmu创建的映射区,单位是4K。

6. Q:如果不检测mmap的返回值,会怎样?
A:各种失败。

7. Q:mmap什么情况下会调用失败?
A: mmap申请的空间不能大于文件大小。

8. Q:对mem越界操作会怎样?
A:同1

9. Q:文件描述符先关闭,对mmap映射有没有影响?
A:没有影响,mmap分配映射区后,通过地址来操作该空间,不使用fd操作。

6. 总结

使用mmap时务必注意以下事项:

 1. 创建映射区的过程中,隐含着一次对映射文件的读操作。
 2. 当MAP_SHARED时,要求:映射区的权限应<=文件打开的权限(出于对映射区的保护)。而MAP_PRIVATE则无所谓,因为mmap中的权限是对内存的限制。
 3. 映射区的释放与文件关闭无关。只要映射建立成功,文件可以立即关闭。
 4. 特别注意,当映射文件大小为0时,不能创建映射区。所以:用于映射的文件必须要有实际大小!!mmap使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。
 5. munmap传入的地址一定是mmap的返回地址。坚决杜绝指针++操作。
 6. 如果文件偏移量必须为4K的整数倍
 7. mmap创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值