mmap 文件不能为空
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *addr, size_t length);
mmap 讲过的人太多了。写这篇的目的,是为了记录今天使用过程中遇到的一个问题:
当映射内存大小大于文件大小时,将导致映射内存无法读写,程序报段错误;
说三遍:文件不能为空!文件不能为空! 文件不能为空!
先说一下解决方案:
打开文件后,调用ftruncate() ,将已打开的文件截断到需要的内存大小即可;
官方推荐:echo 20 > /proc/sys/vm/nr_hugepages;配置20个巨页;配合flags参数使用*//明天试试*
https://man7.org/linux/man-pages/man2/mmap.2.html
看官方文档最靠谱。虽然文档里没说文件不能为空 或者我看漏了
结合百度翻译,简单翻一下,哈哈!
描述
mmap 建立一个到调用继承的虚拟地址空间的映射。addr指定虚拟地址空间的起始地址,length指定映射空间长度(必须大于0);
如果addr 赋NULL,内核选一个页对齐的空闲虚拟空间地址作为起始地址,这是最合适的了;“最好就是传NULL”
如果addr不是NULL, 会以他为基准,找一个页对齐的地址。所以赋值也白赋;
你传的addr甚至可能不是空闲虚拟地址,剩下的还是内核做主;
有名mmap的起始地址由offset这个参数决定,决定从文件offset位置开始映射;还应该是页对齐;
mmap 返回后,文件描述符就可以立马关了, 毕竟mmap可能会增加内核中文件的应用计数;
prot 描述对这块内存期望的权限,w/r/x
flags 决定了公开性,对内存的改变是否对其他使用这个文件mmap的进程可见,不难理解,如果private,可能会单独给这个进程拷贝一份内存;简单点说要进程间共享 就配置MAP_SHARED ;
flags 还有很多其他的属性:
MAP_HUGETLB:这个就是进行巨页映射;可以尽量解决映射长度超出文件长度的问题;
MAP_ANONYMOUS :匿名mmap 没有依赖文件,fd=-1,其缓存长度应该直接与length进行页对齐;
个人分(cai)析(ce)放最后:
- 空文件,内核也没有分配缓存页,返回的只是进程虚拟空间一段空闲空间的起始地址,并没有实现地址映射;
- 映射长度超出文件长度页对齐地址时,也会出现同样的问题;