Linux内存管理之mmap详解
发布网友
发布时间:2024-10-02 05:19
我来回答
共1个回答
热心网友
时间:2024-10-19 05:23
Linux内存管理之mmap详解
一. mmap系统调用
mmap是Linux内核提供的一种功能,用于将文件或其他对象映射到进程的内存中。文件会映射到多个页上,如果文件大小不是所有页大小的总和,那么最后一个页的未使用空间会被清零。munmap则执行相反的操作,移除特定地址区域的对象映射。
使用mmap映射文件到进程后,可以直接操作虚拟地址区域进行文件的读写等操作,无需再调用read,write等系统调用。但需注意,直接对该段内存进行写操作时不会写入超过当前文件大小的内容。
共享内存通信的一个显著优点是效率高,进程可以直接读写内存,而无需数据拷贝。与管道和消息队列等通信方式相比,共享内存只需要两次数据拷贝:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,通信时,进程并不总是读写少量数据后就解除映射,而是保持共享区域,直到通信结束,数据内容一直保存在共享内存中,并在解除映射时写回文件。因此,采用共享内存通信效率非常高。
基于文件的映射,在mmap和munmap执行过程中,被映射文件的st_atime可能被更新。使用PROT_WRITE和MAP_SHARED标志建立的文件映射,其st_ctime和st_mtime在对映射区写入后,但在msync()通过MS_SYNC和MS_ASYNC调用前会被更新。
使用方法:
#include
void *mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *start, size_t length);
返回说明:
成功时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED(其值为(void *)-1),munmap返回-1。错误代码包括EACCES(访问错误)、EAGAIN(文件已被锁定或内存已锁定)、EBADF(无效文件描述符)、EINVAL(参数无效)、ENFILE(文件描述符限制)、ENODEV(文件系统不支持内存映射)、ENOMEM(内存不足)、EPERM(权限不足)、ETXTBSY(以只读方式打开文件,同时指定MAP_DENYWRITE标志)、SIGSEGV(尝试向只读区写入)、SIGBUS(尝试访问不属于进程的内存区)。
参数:
start:映射区的开始地址。
length:映射区的长度。
prot:期望的内存保护标志,不能与文件的打开模式冲突。可通过或运算组合为以下值:PROT_EXEC(可执行)、PROT_READ(可读)、PROT_WRITE(可写)、PROT_NONE(不可访问)。
flags:指定映射对象的类型、映射选项和是否可以共享。值可组合为以下位:MAP_FIXED(使用指定的映射起始地址,如果与现有映射空间重叠,重叠部分将被丢弃。起始地址必须落在页边界上)、MAP_SHARED(与其他所有映射此对象的进程共享映射空间,写入映射区相当于输出到文件,直到msync()或munmap()调用,文件实际上未更新)、MAP_PRIVATE(建立一个写入时复制的私有映射,内存区域的写入不会影响原文件)。
fd:有效的文件描述符。若使用MAP_ANONYMOUS,为了兼容问题,其值应为-1。
offset:被映射对象内容的起点。
二. 系统调用munmap()
#include
int munmap( void * addr, size_t len )。该调用解除进程地址空间中的映射关系,addr是mmap()返回的地址,len是映射区的大小。映射关系解除后,对原映射地址的访问将导致段错误。
三. 系统调用msync()
#include
int msync ( void * addr , size_t len, int flags)。通常,映射空间的更改不会直接写回磁盘文件中,直到munmap()调用后才执行此操作。通过调用msync()可以实现磁盘上文件内容与共享内存区内容的一致性。
四. mmap进行内存映射的原理
mmap系统调用的主要目的是将设备或文件映射到用户进程的虚拟地址空间,实现用户进程对文件的直接读写。此过程分为三步:在用户虚拟地址空间中寻找空闲的满足要求的连续虚拟地址空间(由内核的mmap系统调用完成)、建立虚拟地址空间与文件或设备物理地址之间的映射(通过修改进程页表实现)、在实际访问新映射页面时的操作(由缺页中断完成)。详细描述包括页表管理、虚拟地址与物理地址的映射、缺页异常处理等。
热心网友
时间:2024-10-19 05:24
Linux内存管理之mmap详解
一. mmap系统调用
mmap是Linux内核提供的一种功能,用于将文件或其他对象映射到进程的内存中。文件会映射到多个页上,如果文件大小不是所有页大小的总和,那么最后一个页的未使用空间会被清零。munmap则执行相反的操作,移除特定地址区域的对象映射。
使用mmap映射文件到进程后,可以直接操作虚拟地址区域进行文件的读写等操作,无需再调用read,write等系统调用。但需注意,直接对该段内存进行写操作时不会写入超过当前文件大小的内容。
共享内存通信的一个显著优点是效率高,进程可以直接读写内存,而无需数据拷贝。与管道和消息队列等通信方式相比,共享内存只需要两次数据拷贝:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,通信时,进程并不总是读写少量数据后就解除映射,而是保持共享区域,直到通信结束,数据内容一直保存在共享内存中,并在解除映射时写回文件。因此,采用共享内存通信效率非常高。
基于文件的映射,在mmap和munmap执行过程中,被映射文件的st_atime可能被更新。使用PROT_WRITE和MAP_SHARED标志建立的文件映射,其st_ctime和st_mtime在对映射区写入后,但在msync()通过MS_SYNC和MS_ASYNC调用前会被更新。
使用方法:
#include
void *mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *start, size_t length);
返回说明:
成功时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED(其值为(void *)-1),munmap返回-1。错误代码包括EACCES(访问错误)、EAGAIN(文件已被锁定或内存已锁定)、EBADF(无效文件描述符)、EINVAL(参数无效)、ENFILE(文件描述符限制)、ENODEV(文件系统不支持内存映射)、ENOMEM(内存不足)、EPERM(权限不足)、ETXTBSY(以只读方式打开文件,同时指定MAP_DENYWRITE标志)、SIGSEGV(尝试向只读区写入)、SIGBUS(尝试访问不属于进程的内存区)。
参数:
start:映射区的开始地址。
length:映射区的长度。
prot:期望的内存保护标志,不能与文件的打开模式冲突。可通过或运算组合为以下值:PROT_EXEC(可执行)、PROT_READ(可读)、PROT_WRITE(可写)、PROT_NONE(不可访问)。
flags:指定映射对象的类型、映射选项和是否可以共享。值可组合为以下位:MAP_FIXED(使用指定的映射起始地址,如果与现有映射空间重叠,重叠部分将被丢弃。起始地址必须落在页边界上)、MAP_SHARED(与其他所有映射此对象的进程共享映射空间,写入映射区相当于输出到文件,直到msync()或munmap()调用,文件实际上未更新)、MAP_PRIVATE(建立一个写入时复制的私有映射,内存区域的写入不会影响原文件)。
fd:有效的文件描述符。若使用MAP_ANONYMOUS,为了兼容问题,其值应为-1。
offset:被映射对象内容的起点。
二. 系统调用munmap()
#include
int munmap( void * addr, size_t len )。该调用解除进程地址空间中的映射关系,addr是mmap()返回的地址,len是映射区的大小。映射关系解除后,对原映射地址的访问将导致段错误。
三. 系统调用msync()
#include
int msync ( void * addr , size_t len, int flags)。通常,映射空间的更改不会直接写回磁盘文件中,直到munmap()调用后才执行此操作。通过调用msync()可以实现磁盘上文件内容与共享内存区内容的一致性。
四. mmap进行内存映射的原理
mmap系统调用的主要目的是将设备或文件映射到用户进程的虚拟地址空间,实现用户进程对文件的直接读写。此过程分为三步:在用户虚拟地址空间中寻找空闲的满足要求的连续虚拟地址空间(由内核的mmap系统调用完成)、建立虚拟地址空间与文件或设备物理地址之间的映射(通过修改进程页表实现)、在实际访问新映射页面时的操作(由缺页中断完成)。详细描述包括页表管理、虚拟地址与物理地址的映射、缺页异常处理等。