mmap() - Unix,Linux系统调用
Tutorials Point


  Unix入门
  Unix Shell编程
  高级Unix
  Unix有用参考
  Unix有用资源
  精选阅读

版权所有 © 2014 tutorialspoint



  首页     参考     讨论论坛     关于TP  

mmap() - Unix,Linux系统调用


previous next AddThis Social Bookmark Button

广告

名称

mmap, munmap - 将文件或设备映射到内存或取消映射

概要

#include <sys/mman.h> 

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

int munmap(void *start, size_t length);

描述

mmap() 函数请求将从文件描述符 fd 指定的文件(或其他对象)的偏移量 offset 开始的 length 字节映射到内存中,最好映射到地址 start。 后一个地址只是一个提示,通常指定为 0。 对象实际映射到的位置由 mmap() 返回。

prot 参数描述所需的内存保护(并且不得与文件的打开模式冲突)。 它要么是 PROT_NONE,要么是其他 PROT_* 标志的一个或多个的按位或。

标签描述
PROT_EXEC 页面可以执行。
PROT_READ 页面可以读取。
PROT_WRITE 页面可以写入。
PROT_NONE 页面不可访问。
flags 参数指定映射对象的类型、映射选项以及对页面的映射副本所做的修改是私有的还是与其他引用共享的。 它具有位
标签描述
MAP_FIXED 不要选择与指定地址不同的地址。如果由 startlen 指定的内存区域与任何现有映射的页面重叠,则现有映射的重叠部分将被丢弃。如果指定的地址无法使用,mmap() 将失败。如果指定了 MAP_FIXED,则 start 必须是页面大小的倍数。不鼓励使用此选项。
MAP_SHARED 与映射此对象的所有其他进程共享此映射。 向区域存储等效于写入文件。在调用 msync(2) 或 munmap(2) 之前,文件可能不会实际更新。
MAP_PRIVATE 创建一个私有的写时复制映射。 对区域的存储不会影响原始文件。 mmap() 调用后对文件所做的更改是否在映射区域中可见是不确定的。
必须精确指定 MAP_SHAREDMAP_PRIVATE 之一。

以上三个标志在 POSIX.1-2001 中进行了描述。 Linux 还知道以下非标准标志

标签描述
MAP_DENYWRITE
 此标志被忽略。(很久以前,它表示尝试写入基础文件应该失败并显示 ETXTBUSY。但这导致了拒绝服务攻击。)
MAP_EXECUTABLE
 此标志被忽略。
MAP_NORESERVE
 不要为此映射保留交换空间。当保留交换空间时,可以保证可以修改映射。当不保留交换空间时,如果物理内存不可用,则写入时可能会出现 SIGSEGV。另请参见 proc(5) 中对文件 /proc/sys/vm/overcommit_memory 的讨论。在 2.6 之前的内核中,此标志仅对私有可写映射有效。
MAP_LOCKED(自 Linux 2.5.37 起)
 mlock() 的方式将映射区域的页面锁定到内存中 在较旧的内核中,此标志被忽略。
MAP_GROWSDOWN
 用于堆栈。指示内核虚拟机系统映射应向下扩展到内存中。
MAP_ANONYMOUS
 映射不受任何文件支持;fdoffset 参数被忽略。 自内核 2.4 起,仅在 Linux 上支持将此标志与 MAP_SHARED 结合使用。
MAP_ANON
 MAP_ANONYMOUS 的别名。已弃用。
MAP_FILE
 兼容性标志。被忽略。
MAP_32BIT
 将映射放入进程地址空间的前 2GB 中。设置 MAP_FIXED 时忽略。此标志目前仅在 x86-64 的 64 位程序中受支持。
MAP_POPULATE(自 Linux 2.5.46 起)
 通过对文件执行预读来填充(预取)文件映射的页表。 对映射的后续访问不会因页面错误而被阻塞。
MAP_NONBLOCK(自 Linux 2.5.46 起)
 仅与 MAP_POPULATE 结合使用才有意义。不要执行预读:只为 RAM 中已存在的页面创建页表条目。
某些系统记录了附加标志 MAP_AUTOGROW、MAP_AUTORESRV、MAP_COPY 和 MAP_LOCAL。

除非设置了 MAP_ANONYMOUS,否则 fd 应为有效的文件描述符。如果设置了 MAP_ANONYMOUS,则在 Linux 上忽略 fd。但是,如果指定了 MAP_ANONYMOUS(或 MAP_ANON),某些实现需要 fd 为 -1,并且可移植的应用程序应确保这一点。

offset 应该是 getpagesize(2) 返回的页面大小的倍数。

mmap() 映射的内存在 fork(2) 中保留,具有相同的属性。

文件以页面大小的倍数进行映射。对于不是页面大小倍数的文件,映射时剩余内存将清零,并且对该区域的写入不会写入文件。映射的基础文件大小更改对对应于文件已添加或删除区域的页面的影响是不确定的。

munmap() 系统调用删除指定地址范围的映射,并导致对该范围内的地址的进一步引用生成无效的内存引用。进程终止时,该区域也会自动取消映射。另一方面,关闭文件描述符不会取消映射该区域。

地址 start 必须是页面大小的倍数。包含指示范围一部分的所有页面都被取消映射,随后对这些页面的引用将生成 SIGSEGV。如果指示的范围不包含任何映射的页面,则不会出错。

对于文件支持的映射,映射文件的 st_atime 字段可以在 mmap() 和相应的取消映射之间随时更新;对映射页面的第一次引用将更新该字段(如果尚未更新)。

使用 PROT_WRITEMAP_SHARED 映射的文件的 st_ctimest_mtime 字段将在写入映射区域后以及在随后的 msync()(使用 MS_SYNCMS_ASYNC 标志)之前更新,如果发生这种情况的话。

返回值

成功时,mmap() 返回指向映射区域的指针。出错时,返回 MAP_FAILED 值(即 (void *) -1),并相应地设置 errno。成功时,munmap() 返回 0,失败时返回 -1,并设置 errno(可能设置为 EINVAL)。

注释

PROT_READ 是否包含 PROT_EXEC 取决于体系结构。可移植程序应始终设置 PROT_EXEC,如果他们打算在新映射中执行代码。

错误

标签描述
EACCES 文件描述符引用非规则文件。或者请求了 MAP_PRIVATE,但 fd 未打开以供读取。或者请求了 MAP_SHARED 并设置了 PROT_WRITE,但 fd 未以读/写 (O_RDWR) 模式打开。或者设置了 PROT_WRITE,但文件是仅追加的。
EAGAIN 文件已被锁定,或者锁定了太多内存(参见 setrlimit(2))。
EBADF fd 不是有效的文件描述符(并且未设置 MAP_ANONYMOUS)。
EINVAL 我们不喜欢 startlengthoffset。(例如,它们太大,或者未对齐到页面边界。)
ENFILE 已达到打开文件的系统总数量限制。
ENODEV 指定文件的底层文件系统不支持内存映射。
ENOMEM 没有可用的内存,或者进程的最大映射数将超过。
EPERM prot 参数请求 PROT_EXEC,但映射区域属于已安装为 no-exec 的文件系统上的文件。
ETXTBSY
  设置了 MAP_DENYWRITE,但 fd 指定的对象已打开以供写入。
使用映射区域可能会导致这些信号
SIGSEGV
 尝试写入映射为只读的区域。
SIGBUS 尝试访问缓冲区中不对应于文件的部分(例如,超过文件末尾,包括另一个进程已截断文件的情况)。

可用性

在提供 mmap()、msync() 和 munmap() 的 POSIX 系统上,在 <unistd.h> 中将 _POSIX_MAPPED_FILES 定义为大于 0 的值。(另请参见 sysconf(3)。)

符合标准

SVr4、4.4BSD、POSIX.1-2001。

错误

在 Linux 上,没有上面 MAP_NORESERVE 下建议的保证。默认情况下,当系统内存不足时,任何进程都可能随时被终止。

在 2.6.7 之前的内核中,MAP_POPULATE 标志仅在 prot 指定为 PROT_NONE 时才有效。

另请参见

B.O. Gallmeister,《POSIX.4》,O’Reilly,第 128-129 页和 389-391 页。

previous next Printer Friendly

广告


  

广告



广告