100m光纤做网站,企业机房建设公司,美橙西安网站备案拍照,wordpress好看的背景转自#xff1a;http://blog.csdn.net/yusiguyuan/article/details/23388771 内存映射#xff0c;简而言之就是将用户空间的一段内存区域映射到内核空间#xff0c;映射成功后#xff0c;用户对这段内存区域的修改可以直接反映到内核空间#xff0c;同样#xff0c;内核空… 转自http://blog.csdn.net/yusiguyuan/article/details/23388771 内存映射简而言之就是将用户空间的一段内存区域映射到内核空间映射成功后用户对这段内存区域的修改可以直接反映到内核空间同样内核空间对这段区域的修改也直接反映用户空间。那么对于内核空间----用户空间两者之间需要大量数据传输等操作的话效率是非常高的。 以下是一个把普遍文件映射到用户空间的内存区域的示意图。 图一 二、基本函数 mmap函数是unix/linux下的系统调用详细内容可参考《Unix Netword programming》卷二12.2节。 mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的当然mmap()实现共享内存也是其主要应用之一。 mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后进程可以像访问普通内存一样对文件进行访问不必再调用read()write等操作。mmap并不分配空间, 只是将文件映射到调用进程的地址空间里但是会占掉你的 virutal memory, 然后你就可以用memcpy等操作写文件, 而不用write()了.写完后内存中的内容并不会立即更新到文件中而是有一段时间的延迟你可以调用msync()来显式同步一下, 这样你所写的内容就能立即保存到文件里了.这点应该和驱动相关。 不过通过mmap来写文件这种方式没办法增加文件的长度, 因为要映射的长度在调用mmap()的时候就决定了.如果想取消内存映射可以调用munmap()来取消内存映射 void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) mmap用于把文件映射到内存空间中简单说mmap就是把一个文件的内容在内存里面做一个映像。映射成功后用户对这段内存区域的修改可以直接反映到内核空间同样内核空间对这段区域的修改也直接反映用户空间。那么对于内核空间----用户空间两者之间需要大量数据传输等操作的话效率是非常高的。 原理 首先“映射”这个词就和数学课上说的“一一映射”是一个意思就是建立一种一一对应关系在这里主要是只 硬盘上文件 的位置与进程 逻辑地址空间 中一块大小相同的区域之间的一一对应如图1中过程1所示。这种对应关系纯属是逻辑上的概念物理上是不存在的原因是进程的逻辑地址空间本身就是不存在的。在内存映射的过程中并没有实际的数据拷贝文件没有被载入内存只是逻辑上被放入了内存具体到代码就是建立并初始化了相关的数据结构struct address_space这个过程有系统调用mmap()实现所以建立内存映射的效率很高。 图1.内存映射原理 既然建立内存映射没有进行实际的数据拷贝那么进程又怎么能最终直接通过内存操作访问到硬盘上的文件呢那就要看内存映射之后的几个相关的过程了。 mmap()会返回一个指针ptr它指向进程逻辑地址空间中的一个地址这样以后进程无需再调用read或write对文件进行读写而只需要通过ptr就能够操作文件。但是ptr所指向的是一个逻辑地址要操作其中的数据必须通过MMU将逻辑地址转换成物理地址如图1中过程2所示。这个过程与内存映射无关。 前面讲过建立内存映射并没有实际拷贝数据这时MMU在地址映射表中是无法找到与ptr相对应的物理地址的也就是MMU失败将产生一个缺页中断缺页中断的中断响应函数会在swap中寻找相对应的页面如果找不到也就是该文件从来没有被读入内存的情况则会通过mmap()建立的映射关系从硬盘上将文件读取到物理内存中如图1中过程3所示。这个过程与内存映射无关。 如果在拷贝数据时发现物理内存不够用则会通过虚拟内存机制swap将暂时不用的物理页面交换到硬盘上如图1中过程4所示。这个过程也与内存映射无关。 效率 从代码层面上看从硬盘上将文件读入内存都要经过文件系统进行数据拷贝并且数据拷贝操作是由文件系统和硬件驱动实现的理论上来说拷贝数据的效率是一样的。但是通过内存映射的方法访问硬盘上的文件效率要比read和write系统调用高这是为什么呢原因是read()是系统调用其中进行了数据拷贝它首先将文件内容从硬盘拷贝到内核空间的一个缓冲区如图2中过程1然后再将这些数据拷贝到用户空间如图2中过程2在这个过程中实际上完成了 两次数据拷贝 而mmap()也是系统调用如前所述mmap()中没有进行数据拷贝真正的数据拷贝是在缺页中断处理时进行的由于mmap()将文件直接映射到用户空间所以中断处理函数根据这个映射关系直接将文件从硬盘拷贝到用户空间只进行了 一次数据拷贝 。因此内存映射的效率要比read/write效率高。 图2.read系统调用原理 下面这个程序通过read和mmap两种方法分别对硬盘上一个名为“mmap_test”的文件进行操作文件中存有10000个整数程序两次使用不同的方法将它们读出加1再写回硬盘。通过对比可以看出read消耗的时间将近是mmap的两到三倍。 1 #includeunistd.h2 3 #includestdio.h4 5 #includestdlib.h6 7 #includestring.h8 9 #includesys/types.h10 11 #includesys/stat.h12 13 #includesys/time.h14 15 #includefcntl.h16 17 #includesys/mman.h18 19 20 21 #define MAX 1000022 23 24 25 int main()26 27 {28 29 int i0;30 31 int count0, fd0;32 33 struct timeval tv1, tv2;34 35 int *array (int *)malloc( sizeof(int)*MAX );36 37 38 39 /*read*/40 41 42 43 gettimeofday( tv1, NULL );44 45 fd open( mmap_test, O_RDWR );46 47 if( sizeof(int)*MAX ! read( fd, (void *)array, sizeof(int)*MAX ) )48 49 {50 51 printf( Reading data failed.../n );52 53 return -1;54 55 }56 57 for( i0; iMAX; i )58 59 60 61 array[ i ];62 63 if( sizeof(int)*MAX ! write( fd, (void *)array, sizeof(int)*MAX ) )64 65 {66 67 printf( Writing data failed.../n );68 69 return -1;70 71 }72 73 free( array );74 75 close( fd );76 77 gettimeofday( tv2, NULL );78 79 printf( Time of read/write: %dms/n, tv2.tv_usec-tv1.tv_usec );80 81 82 83 /*mmap*/84 85 86 87 gettimeofday( tv1, NULL );88 89 fd open( mmap_test, O_RDWR );90 91 array mmap( NULL, sizeof(int)*MAX, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );92 93 for( i0; iMAX; i )94 95 96 97 array[ i ];98 99 munmap( array, sizeof(int)*MAX );
100
101 msync( array, sizeof(int)*MAX, MS_SYNC );
102
103 free( array );
104
105 close( fd );
106
107 gettimeofday( tv2, NULL );
108
109 printf( Time of mmap: %dms/n, tv2.tv_usec-tv1.tv_usec );
110
111
112
113 return 0;
114
115 } 输出结果 Time of read/write: 154msTime of mmap: 68ms 转载于:https://www.cnblogs.com/wanpengcoder/articles/5306688.html