实验3 linux内存映射,Linux下的内存映射函数mmap详解及示例代码 - Go语言中文社区

实验3 linux内存映射,Linux下的内存映射函数mmap详解及示例代码


Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明:

头文件:

原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);

返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).

参数:

addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.

length: 将文件的多大长度映射到内存.

prot: 映射区的保护方式, 可以是:

PROT_EXEC: 映射区可被执行.

PROT_READ: 映射区可被读取.

PROT_WRITE: 映射区可被写入.

PROT_NONE: 映射区不能存取.

flags: 映射区的特性, 可以是:

MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.

MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.

此外还有其他几个flags不很常用, 具体查看linux C函数说明.

fd: 由open返回的文件描述符, 代表要映射的文件.

offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.

下面说一下内存映射的步骤:

用open系统调用打开文件, 并返回描述符fd.

用mmap建立内存映射, 并返回映射首地址指针start.

对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).

用munmap(void *start, size_t lenght)关闭内存映射.

用close系统调用关闭文件fd.

注意事项:

在修改映射的文件时, 只能在原长度上修改, 不能增加文件长度, www.linuxidc.com因为内存是已经分配好的.

Linux-mmap函数介绍(转)

mmap函数是unix/linux下的系统调用,来看《Unix Netword programming》卷二12.2节对mmap的介绍:

The mmap function maps either a file or a Posix shared memory object into the address space of a process.We use this function for three purposes:

1. with a regular file to provide memory-mapped I/O

2. with special files to provide anonymous memory mappings

3. with shm_open to provide Posix shared memory between unrelated processes

mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。

mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。

我们的程序中大量运用了mmap,用到的正是mmap的这种“像访问普通内存一样对文件进行访问”的功能。实践证明,当要对一个文件频繁的进行访问,并且指针来回移动时,调用mmap比用常规的方法快很多。

来看看mmap的定义:

void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);

参数fd为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信)。

len是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。

prot参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读),PROT_WRITE(可写),PROT_EXEC(可执行),PROT_NONE(不可访问)。

flags由以下几个常值指定:MAP_SHARED, MAP_PRIVATE, MAP_FIXED。其中,MAP_SHARED,MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。

如果指定为MAP_SHARED,则对映射的内存所做的修改同样影响到文件。如果是MAP_PRIVATE,则对映射的内存所做的修改仅对该进程可见,对文件没有影响。

offset参数一般设为0,表示从文件头开始映射。

参数addr指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。

看看下面这个图(来自《Unix Netword programming》卷二12.2节),对mmap进一步加深印象:

这里不再详细介绍mmap的参数,读者可参考mmap手册页或者《Unix Netword programming》卷二12.2节获得进一步的信息。         最后,举个例子来结束本节。4.2节说过,Fileinformation数组是以二进制的形式写进一个叫inforindex的文件中。那么,当要访问Fileinformation数组时,代码类似这样:

struct stat st;

char buffer=” inforindex”;

Fileinformation *_fileinfoIndexptr = NULL;

if(stat(buffer,&st)<0)

{

fprintf(stderr,"error to stat %sn",buffer);

exit(-1);

}// mmap the inforindex to _fileinfoIndexptr

int fd=open(buffer, O_RDONLY);

if(fd<0)

{

printf("error to open %sn",buffer);

exit(-1);

}

_fileinfoIndexptr   = (Fileinformation*)mmap(NULL,st.st_size, PROT_READ,MAP_SHARED,fd,0);

if(MAP_FAILED == _fileinfoIndexptr)

{

printf("error to mmap %sn",buffer);

close(fd);

exit(-1);

}

close(fd);0b1331709591d260c1c78e86d0c51c18.png

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_39918043/article/details/116844590
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-17 08:07:21
  • 阅读 ( 1331 )
  • 分类:Linux

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢