mmap、munmap函数

#include <sys/mman.h>

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

int munmap(void *addr, size_t length);

 

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

返回:成功,返回创建的映射区首地址(其返回的地址可以作为数组的首地址来使用);失败,返回MAP_FAILED(宏)。

addr:建立映射区的首地址,由Linux内核指定。使用时,直接传递NULL

length:欲创建映射区的大小(必须小于文件大小);

prot:映射区权限PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE(两个宏位或);

flags:标志位参数(常用于设定更新物理区域、设置共享、创建匿名映射区),MAP_SHARED:会将映射区所做的操作反映到物理设备(磁盘)上,MAP_PRIVATE:映射区所做的修改不会反映到物理设备;

fd:用来建立映射区的文件描述符

offset:映射文件的偏移4k的整数倍),即只是映射文件的部分,不是从开始处映射。

 

int munmap(void *addr, size_t length);

同malloc(new)函数申请内存空间类似的,mmap建立的映射区在使用结束后也应调用类似free(delete)的函数来释放。

addr:映射区的首地址   length:映射区的长度

成功:0,失败:-1

 

两个函数的注意事项:

1.创建映射区的过程中,隐含着一次对映射文件的读操作,因此在打开文件时必须包括读权限,才能创建映射区;

2.当MAP_SHARED时,要求:映射区的权限应 <=文件打开的权限(出于对文件的保护)。而MAP_PRIVATE则无所谓,因为mmap中的权限是对内存的限制;

3.映射区的释放与文件关闭无关。只要映射建立成功,文件可以立即关闭。在建立好映射区之后就可以关闭文件了,以后在对映射区的读写操作不再需要文件描述符了,因为映射关系已经被mmap系统调用确定了。

4.特别注意,当映射文件大小为0时,不能创建映射区。所以:用于映射的文件必须要有实际大小!不能为0mmap使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。malloc(或new)分配的地址大小(堆空间)都可以指定为0(使用完后,需要free(或delete)释放),但是mmap不可以!!

5.munmap传入的地址一定是mmap的返回地址,坚决杜绝指针++操作(必须完全对应);

6.文件偏移量必须为4K的整数倍,因为MMU完成了从线性地址到物理地址的映射,映射时以页为单位进行的,一页一页进行映射;

7.mmap创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。

因此,对于新创建的文件,必须对文件进行拓展(ftruncate、truncate和lseek),然后才能创建映射区。对于lseek、mmap等函数的指针移动都是以字节为单位的(char为1个字节)。

Linux中,`mmap`函数用于在进程的虚拟地址空间中创建一个新的映射区域或者修改已有映射区域的属性。它可以将文件或其他设备映射到内存中,也可以用于创建匿名映射。 下面是`mmap`函数的原型: ```c #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); ``` 参数说明: - `addr`:映射区域的首地址,一般传入`NULL`,让系统自动选择合适的地址。 - `length`:映射区域的长度。 - `prot`:映射区域的保护模式,可以是`PROT_READ`、`PROT_WRITE`、`PROT_EXEC`的组合。 - `flags`:映射区域的标志,可以是`MAP_SHARED`、`MAP_PRIVATE`、`MAP_ANONYMOUS`等。 - `fd`:要映射的文件描述符,如果不需要映射文件,则传入`-1`。 - `offset`:要映射文件的偏移量。 调用成功时,`mmap`函数返回映射区域的起始地址,失败时返回`MAP_FAILED`。 以下是一个简单的示例,演示了如何使用`mmap`函数将文件映射到内存中: ```c #include <stdio.h> #include <stdlib.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> int main() { int fd; char *data; fd = open("file.txt", O_RDWR); if (fd == -1) { perror("open"); exit(1); } // 获取文件大小 off_t file_size = lseek(fd, 0, SEEK_END); if (file_size == -1) { perror("lseek"); exit(1); } // 将文件映射到内存中 data = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { perror("mmap"); exit(1); } // 使用映射的内存进行操作 printf("%s\n", data); // 解除内存映射 if (munmap(data, file_size) == -1) { perror("munmap"); exit(1); } close(fd); return 0; } ``` 这个示例中,首先通过`open`函数打开一个文件,然后使用`lseek`函数获取文件的大小。接下来,使用`mmap`函数将文件映射到内存中,并返回映射区域的起始地址。最后,通过使用映射的内存进行操作,完成后使用`munmap`函数解除内存映射。 需要注意的是,`mmap`函数将文件映射到内存中后,对内存的操作将直接反映到文件中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值