赞
踩
目录
使一个磁盘文件与内存中的一个缓冲区相映射,进程可以像访问普通内存一样对文件进行访问,不必再调用read,write。
注意事项:
(1) 创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区。
(2) 当MAP_SHARED时,要求:映射区的权限应 <=文件打开的权限(出于对映射区的保护),如果不满足报非法参数(Invalid argument)错误。
当MAP_PRIVATE时候,mmap中的权限是对内存的限制,只需要文件有读权限即可,操作只在内存有效,不会写到物理磁盘,且不能在进程间共享。
(3) 映射区的释放与文件关闭无关,只要映射建立成功,文件可以立即关闭。(没映射成功前不能关闭)
(4) 用于映射的文件大小必须>0,当映射文件大小为0时,指定非0大小创建映射区,访问映射地址会报总线错误,指定0大小创建映射区,报非法参数错误(Invalid argument)
(5) 文件偏移量必须为0或者4K的整数倍(不是会报非法参数Invalid argument错误).
(操作系统的内存是一页一页分配的一页就是4k)
(6)映射大小可以大于文件大小,但只能访问文件page的内存地址,否则报总线错误(下图中剩余部分) ,超出映射的内存大小报段错误
读程序:
- #if 1
-
-
- #include <sys/mman.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
-
- int main(){
-
- void *addr;
- int fd;
- fd =open("test",O_RDWR);
- if(fd<0){
- perror("open");
- return 0;
- }
- int len = lseek(fd,0,SEEK_END);
- addr = mmap(NULL,2048, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if(addr == MAP_FAILED){
- perror("mmap");
- return 0;
- }
- close(fd);
- // memcpy((addr),"99999999999999",15);
- while(1){
- printf("read=%s\n",(char*)(addr));
- sleep(1);
- }
-
-
- }
- #endif

写程序:
- #include <sys/mman.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
-
- int main(){
-
- void *addr;
- int fd;
- fd =open("test",O_RDWR);
- if(fd<0){
- perror("open");
- return 0;
- }
- int len = lseek(fd,0,SEEK_END);
- addr = mmap(NULL,2048, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- if(addr == MAP_FAILED){
- perror("mmap");
- return 0;
- }
- close(fd);
- memcpy(addr,"aaaaaaaaaaaaaaa",15);
- int i=0;
- while(i<2048){
- memcpy((addr+i),"a",1);
- i++;
- sleep(1);
- }
- //memcpy(addr,"abcdefg",7);
-
-
- //printf("read=%s\n",(char*)(addr));
-
-
-
- }

会发现报了总线错误。对应注意中的第六条
给他加了22个空格
这是现象,是不是很奇怪。
左面就是先写了15个a然后从第一个位置开始往后写,右面是一直读。这就是为什么前面都一样长因为它有初值了。i大于15时才会显现出来。验证一下
把开始的初值改成空格
并且不写入字符串结束标志
因为开始有初值所以变成这个形状了,我们还发现一个问题,没有字符串结束标志后开始没换行了,现在把test清空测一下。
就变成这个样子了。
发现当超过限制后就没换行了,这个addr的最后是有一个换行的,当把他覆盖掉后就没了。他最多可以多打印四个。
事实证明这个长度最多就是和test的大小一致,可以突破限制多打印的数量是随机的有时候多4个有时候多一个,这个和内存中字符串结束标志在哪可能有关,毕竟是已经超出可控范围的东西。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。