mmap函数大文件读写可能出现的问题

本文介绍了mmap函数的应用场景及其实现文件映射至内存的过程,并总结了使用mmap时可能遇到的问题及其解决办法。

转载:http://www.chineselinuxuniversity.net/articles/41953.shtml

-------------------------------------------------------------------------

 mmap函数实现把一个文件映射到一个内存区域,从而我们可以像读写内存一样读写文件,他比单纯调用read/write也要快上许多。在某些时候我们可以把内存的内容拷贝到一个文件中实现内存备份,当然,也可以把文件的内容映射到内存来恢复某些服务。另外,mmap实现共享内存也是其主要应用之一,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。

  关于mmap的内容请看《Unix环境高级编程》12章。在这里,说一下使用mmap函数时可能遇到的问题:

  //下面的代码把文件1.ls中的内容通过mmap函数写入2.ls中,忽略出错处理

  int fd=open("1.ls",O_RDONLY);

  int fd2=open("2.ls",O_CREAT|O_RDWR|O_TRUNC,S_IRUSR|S_IWUSR);//必须设置读写权限,若只有写权限,会产生SIGSEGV信号

  //mmap进行文件映射时必须先读取文件`

  struct stat st;

  fstat(fd,&st);

  lseek(fd2,st.st_size-1,SEEK_SET);

  write(fd2,"",1);        //必须的,如果不设置,当写入数据的时候会遇到文件结束符,产生SIGBUS信号

  void *_src=mmap(NULL,st.st_size,PROT_READ,MAP_SHARED, fd,0);

  void *_des=mmap(NULL,st.st_size,PROT_WRITE,MAP_SHARED,fd2,0);

  close(fd);      //关闭文件后 依然可修改文件内容

  close(fd2);

  memcpy(_des,_src,st.st_size);

  总结一下,可能产生的问题如下:

  1.进行文件映射的描述符必须拥有读权限,否则会产生SIGSEGV信号

  2.把内存内容写入映射文件时,必须确保被写文件当前位置到文件结尾的长度不小于所写内容长度,否则产生SIGBUS信号

  3.关闭文件描述符并不能保证文件内容不被修改

  4.munmap并不能使映射的内容写回磁盘


在C语言中,可以使用`mmap()`系统调用来将整个文映射到进程地址空间,这样可以直接通过内存操作来读写,而无需频繁的I/O操作。下面是一个简单的测试程序示例,它会打开一个文,然后使用`mmap()`将其加载到内存,进行读取和写入: ```c #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #define FILE_NAME "test_file.txt" int main() { int fd; // 文描述符 char *mapped_addr; // 映射后的地址 off_t length; ssize_t read_size; int ret; // 打开文 if ((fd = open(FILE_NAME, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { perror("Failed to open file"); return 1; } // 获取文长度 lseek(fd, 0, SEEK_END); length = ftell(fd); lseek(fd, 0, SEEK_SET); // 重置指针 // 映射文 if ((mapped_addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { perror("Failed to mmap file"); close(fd); return 1; } printf("Mapped %zd bytes at %p\n", length, mapped_addr); // 读取数据 for (read_size = 1; read_size <= length; read_size++) { if ((ret = read(fd, mapped_addr, read_size)) == -1) { perror("Reading from file failed"); break; } printf("Read %zd bytes: ", ret); for (int i = 0; i < ret; i++) { printf("%c ", mapped_addr[i]); } printf("\n"); } // 写入数据 char write_data[] = "Hello, Mapped File!"; for (size_t i = 0; i < sizeof(write_data); i++) { mapped_addr[i] = write_data[i]; } // 修改后同步至磁盘 msync(mapped_addr, length, MS_SYNC); // 释放映射 munmap(mapped_addr, length); // 关闭文 close(fd); return 0; } ``` 这个程序首先打开一个文,然后创建一个内存映射,并读取文内容到内存。接着,它在内存中写入一些字符串,然后同步内存更新回磁盘,最后释放内存映射并关闭文
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值