| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 3857 人关注过本帖
标题:mmap() 函数的一点点介绍
只看楼主 加入收藏
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
结帖率:98.63%
收藏
已结贴  问题点数:20 回复次数:13 
mmap() 函数的一点点介绍
看虚拟内存的时候有很多不明白,所以干脆停下来看一看mmap()的一些实例。

于是分析了一下,拿出来分享。下面是一段简单的映射一段内存放文件的程序示例mmap()的用法


程序代码:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main(int argc, char *argv[]) {

        struct stat sb;

        off_t len;
     
        char *p;

        int fd; 

        if( argc < 2 ) {

                fprintf( stderr, "usage: %s <file>\n", argv[0]);

                return 1;
        }

        fd = open ( argv[1], O_RDONLY );

        if ( fd == -1) {

                perror( "open" );

            return 1;
        }

        if( fstat ( fd, &sb ) == -1 ) {

                perror ( "fstat" );

                return 1;
        }
    
        if ( !S_ISREG( sb.st_mode ) ) {
               
                fprintf( stderr, "%s is not a file\n",argv[1]);
                
                return 1;
        }
    
        p = mmap ( 0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0 );

        if( p == MAP_FAILED ) {

                perror( "mmap" );

                return 1;
        }

        if ( close(fd) == -1) {
                perror( "close" );

                return 1;
        }

        for ( len = 0; len < sb.st_size; len++) 

                putchar (p[len]);

        if( munmap( p, sb.st_size) == -1 ) {

                perror( "munmap" );

                return 1;
        }
    
        return 0;
}


给出一个mmap的原型吧
void *
mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

程序中addr若为0, 则系统帮你从哪里开始映射,一般都会选择0吧

len 则是从fstat中获得

prot则是保护标志,程序里被标志为PROT_READ(页可以被读)

flags 则指定了被映射的对象的类型。MAP_SHARED把它标记标记为共享,

也就是说在一个进程中写入那个区域后会影响其它进程(同样被映射到那个区域的进程)

S_ISREG是一个宏用来检测信息,这样我们就可以知道给出的文件是不是regular file


通过mmap() 函数来操纵文件有而不是使用read()或者是write()有一些好处。

读写内存映射文件(memory-mapped file) 可以避免在使用read()

或者是write()时碰到的一些不必要的复制。

用read() 和 write() 时, 要先把数据从内核缓冲区复制到应用程序的缓冲区或者相反。

为什么GNU grep 很快,就是因为grep曾经默认使用mmap()而很努力的避开输入中使用read()

从而避免无谓的复制。

比如数据必须先被复制到user-space buffer中或是必须先从user-space buffe中复制出来

读写内存映射文件(memory-mapped file)并且不会有任何不必要的系统调用(system call) 或者是

进程切换(context switch). 和访问内存一样简单

但是使用mmap()是需要注意的则是内存的浪费问题

比如对于一个4kb的页, 如果只是映射7byte,,那就是有4089 byte 被浪费了,

因为出映射出来的内存都是整数大小.


提示:

可以映射至设备文件/dev/zero来实现匿名内存映射。

fd = open ( "/dev/zero", O_RDONLY );

ptr = mmap( 0, desired_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0 );

close(fd);

与下面一行代码是等效的

ptr = mmap ( 0,  desired_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0 );

注: /dev/zero 是一个永远输出0 的特殊文件

如果指定了MAP_ANONYMOUS(匿名映射,则不需要和任何文件关联)此时fd要指定为-1


[ 本帖最后由 madfrogme 于 2012-8-21 19:20 编辑 ]
搜索更多相关主题的帖子: 虚拟内存 
2012-08-21 18:16
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:5 
学习
2012-08-21 18:18
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
收藏
得分:0 
Z版如鬼魅一般学习着

The quieter you become, the more you can hear
2012-08-21 18:19
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
你们一放分 我闻着味就来了
2012-08-21 18:21
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:5 
接分狂,20分也要。

授人以渔,不授人以鱼。
2012-08-21 18:23
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
收藏
得分:0 
你也辛苦了

The quieter you become, the more you can hear
2012-08-21 18:23
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
收藏
得分:0 
分这种东西都是浮云,以后大家问完问题还是分享神马的之后散一张MM照才是王道啊

The quieter you become, the more you can hear
2012-08-21 18:25
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
这玩意不就相当于win里面的内存映射文件么
2012-08-21 18:26
madfrogme
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:21
帖 子:1160
专家分:1106
注 册:2009-6-24
收藏
得分:0 
应该是的吧,最近想深入了解一下虚拟地址转物理地址的过程,所以把一些基本的东西巩固一下

The quieter you become, the more you can hear
2012-08-21 18:30
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用madfrogme在2012-8-21 18:30:35的发言:

应该是的吧,最近想深入了解一下虚拟地址转物理地址的过程,所以把一些基本的东西巩固一下

这个转换很复杂啊 祝你成功。。

顺便结题散分罢
2012-08-21 18:32
快速回复:mmap() 函数的一点点介绍
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.025482 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved