mmap系统调用

来源:互联网 发布:mac谷歌浏览器无法登录 编辑:程序博客网 时间:2024/05/01 10:01

转载 http://blog.csdn.net/todd911/article/details/18794269

《UNIX环境高级编程》笔记--存储映射IO

原创 2014年01月27日 16:27:49
  • 存储映射IO使一个磁盘文件与存储空间中的一个缓冲区相映射。于是当从缓冲区中取数据,就相当于读文件中的相应的字节;

将数据存入缓冲区,则相应字节就自动写入文件,这样就可以在不是用read和write的情况下执行IO。

这可以通过mmap函数实现。

[cpp] view plain copy
  1. #include<sys/mman.h>  
  2. void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);  
  3. //成功则返回映射区的起始地址,出错则返回MAP_FAILED  

addr参数用于指定映射区的起始地址。通常将其设置为0,这表示由系统选择该映射区的起始地址。提高移值性。不为0只是建议操作系统。

映射区的起始地址。

filedes指定要被映射文件的描述符。

len是映射的字节数。

off是要映射字节在文件中的起始偏移量。

prot参数说明对映射存储区的保护要求,见下表。


可以通过按位或指定任意组合,但是要求不能超过文件open模式访问权限。

flag参数影响存储区的多种属性。

MAP_FIXED :返回值必须等于addr。因为这不利于可移植性,所以不鼓励使用,如果未指定标志,而且addr非0,则内核

只把addr视为在何处设置映射区的一种建议,但是不保证会使用所要求的地址。

MAP_SHARED:这一标志说明了本进程对映射区所进行的存储操作的配置。此标志指定存储操作修改映射文件,这就是

说,存储操作相当于对该文件的write。必须指定本标志或下一个标志(MAP_PRIVATE),但不能同时指定。

MAP_PRIVATE:本标志说明,对映射区的存储操作导致创建该映射文件的一个私有副本。所有后来对该映射区的引用都

是引用该副本,而不是原始文件。


存储映射文件在进程内存空间中的安排如下:


off和addr的值通常应当是系统虚拟内存页长度的倍数。因为映射文件的起始偏移量受系统虚拟内存页长度的限制,那么如

果映射区的长度不是页长的整数倍时,将如何呢?假定文件长12字节,系统页长512字节,则系统通常提供512字节的映射

区,其中后500个字节被设置为0.


调用mprotect可以更改一个现存映射存储区的权限。

[cpp] view plain copy
  1. #include<sys/mman.h>  
  2. int mprotect(void *addr, size_t len, int prot);  
  3. //若成功返回0,出错则返回-1.  
prot的许可值与mmap中prot参数一样。


如果在共享存储映射区中的页已被修改,那么我们可以调用msync将该页冲洗到被映射的文件中,msync函数类似于

fsync,但作用于存储映射区。

[cpp] view plain copy
  1. #include<sys/mman.h>  
  2. int msync(void *addr, size_t len, int flag);  
  3. //若成功则返回0,出错则返回-1.  
flag参数是我们对如何冲洗存储区有某种程度的控制。

MS_ASYNC:简化被写页的调度。

MS_SYNC:在返回之前等待写操作完成。(一定要指定MS_ASYNC和MS_SYNC中的一个)

MS_INVALIDATE是一个可选标志,使用它们以通知操作系统丢弃与地层存储器没有同步的任何页。


进程终止时,或调用munmap之后,存储营社区就被自动解除映射。关闭文件描述符filedes并不解除映射区。

[cpp] view plain copy
  1. #include<sys/mman.h>  
  2. int munmap(caddr_t addr, size_t len);  
  3. //若成功则返回0,出错则返回-1.  
munmap不会影响被映射的对象,也就是说,调用munmap不会使营社区的内容写到磁盘文件上。对于MAP_SHARED区

磁盘文件的更新,在写到存储映射区时按内核虚拟内存算法自动进行,在解除了映射后,对于MAP_PRIVATE存储区的修改

被丢弃。

实践:

  1 #include <stdio.h>  2 #include <unistd.h>  3 #include <stdlib.h>  4 #include <sys/mman.h>  5 #include <fcntl.h>  6 int main()  7 {  8     int fr=open("a.txt",O_RDWR);  9     if(fr<0)                                                                                                                                                                              10     { 11         exit(0); 12     } 13     char *buf = (char*)mmap(NULL, 100, PROT_READ|PROT_WRITE, MAP_SHARED, fr,0); //IMPORT FLAG 14     int i; 15     while(buf[i]!='\0') 16     { 17         printf("%c\n",buf[i++]); 18     } 19  20 }



原创粉丝点击