2019-10-14 mmap,mremap,munmap,msync

mmap,mremap,munmap,msync详解

mmap

概述:

一种内存映射文件的方法:

mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。即映射长度最小都是一内存页。

mmap操作提供了一种机制,让用户程序直接访问设备内存,这种机制,相比较在用户空间内核空间互相拷贝数据,效率更高。在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍,面向流的设备不能进行mmap,mmap的实现和硬件有关。

文件一旦被映射后,调用mmap()的进程对返回地址的访问是对某一内存区域的访问,暂时脱离了磁盘上文件的影响。只有在调用了munmap()后或者msync()时,才把内存中的相应内容写回磁盘文件,所写内容仍然不能超过文件的大小。

函数:

#include <sys/mman.h>
函数原型
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);

参数:
start:映射区的开始地址,设置为0时表示由系统决定映射区的起始地址。
length:映射区的长度。//长度单位是 以字节为单位,不足一内存页按一内存页处理
prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通
过 | 运算合理地组合在一起

	PROT_EXEC //页内容可以被执行
	PROT_READ //页内容可以被读取
	PROT_WRITE //页可以被写入
	PROT_NONE //页不可访问
	
flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者
	   多个以下位的组合体
    MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重
    叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会
    失败。并且起始地址必须落在页的边界上。
    MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,
    相当于输出到文件。
    MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文
    件。这个标志和MAP_SHARED标志是互斥的,只能使用其中一个。
    MAP_DENYWRITE //这个标志被忽略。
    MAP_EXECUTABLE //同上
    MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区
    修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引
    起段违例信号。
    MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
    MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
    MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
    MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。
    MAP_FILE //兼容标志,被忽略。
    MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当
    前这个标志只在x86-64平台上得到支持。
    MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不
    会被页违例阻塞。
    MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已
    存在于内存中的页面建立页表入口。
    
fd:有效的文件描述词。一般是由open()函数返回,其值也可以设置为-1,此时需要指
定flags参数中的MAP_ANONYMOUS,表明进行的是匿名映射,只能用于具有亲缘关系的进
程间通信。
off_toffset:被映射对象内容的起点。

返回值:
成功执行时,mmap()返回被映射区的指针。失败时,mmap()返回MAP_FAILED。

应用:

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

mremap

概述:

重新映射虚拟内存地址。

函数:

#include <sys / mman.h>

void * mremap(void * old_address ,size_t old_size ,
			size_t new_size ,int flags ,... / * void * new_address  * /;

参数:
old_address:是您所使用的虚拟内存块的旧地址想要扩大(或缩小)。注意old_address必须是页面对齐
old_size:是虚拟内存块的旧大小。如果old_size的值为零,则mremap()将创建
       	  相同页面的新映射。new_size将是新映射的大小。
new_size:是请求后虚拟内存块的大小。
flags:默认情况下,如果没有足够的空间在当前位置展开映射,则  mremap()失败。
	MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
	MREMAP_FIXED  (从Linux 2.3.31开始)
	mremap()接受第五个参数  void * new_address,该参数指定映射必须移至页
	面对齐地址。在new_address和new_size指定的地址范围内的所有先前映射都不会
	被映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE。
	
new_address:可选择映射地址的位置,也可NULL,系统返回映射地址。

返回值:
成功时,mremap()返回一个指向新虚拟内存区域的指针。
错误时,将返回值MAP_FAILED

应用:

修改文件后,文件大小发生改变,通常与ftruncate()连用,ftruncate()用于修改文件大小,然后进行可进行重新映射mremap()。

int ftruncate(int fd,off_t length);
功能:
将参数fd指定的文件大小改为参数length指定的大小。

返回值:
执行成功则返回0,失败返回-1。

munmap

概述:

用来解除内存映射。当进程结束或利用exec相关函数来执行其他程序时,映射内存会自动解除,但关闭对应的文件描述符时不会解除映射。

函数:
 #include<unistd.h>
 
 int munmap(void *start,size_t length);
 
  参数:
  start:所指的映射内存起始地址。
  length:取消的内存大小。
  
  返回值:
  如果解除映射成功则返回0,否则返回-1

msync

概述:

刷新映射空间的对共享内容的改变,写到磁盘,使磁盘文件内容与共享内存区中的内容一致。往往在调用munmap()后才执行该操作。

函数:
#include<sys/mman.h>

int msync ( void * addr, size_t len, int flags);

参数:
	addr:文件映射到进程空间的地址;
	len:映射空间的大小;
	flags:刷新的参数设置:
		  MS_ASYNC(异步)时,调用会立即返回,不等到更新的完成;
		  MS_SYNC(同步)时,调用会等到更新完成之后返回;
		  MS_INVALIDATE(通知使用该共享区域的进程,数据已经改变)时,在共享
		  内容更改之后,使得文件的其他映射失效,从而使得共享该文件的其他进程
		  去重新获取最新值;
		  
返回值:
成功则返回0;失败则返回-1;
### 如何使用 `--stream-mmap` 参数在 FFmpeg 中进行流式处理 FFmpeg 是一个强大的多媒体处理工具,能够通过多种参数实现不同的功能。对于 `--stream-mmap` 参数,在实际命令行调用中并不存在此确切命名的选项;然而,存在类似的机制来利用内存映射文件 (mmap) 进行高效的媒体流传输。 当涉及到高效读取大文件或网络流时,可以通过 `-use_mmap` 选项启用内存映射文件的支持[^1]: ```bash ffmpeg -re -i input.mp4 -vcodec copy -acodec copy -f mpegts udp://destination_ip:port?pkt_size=1316&buffer_size=65535&use_mmap=1 ``` 上述命令展示了如何设置 UDP 流输出的同时开启内存映射支持。需要注意的是,不是所有的协议都支持该特性,并且具体效果取决于操作系统以及硬件环境。 另外一种情况可能是误认为 `--stream-mmap` 属于某些特定版本或者编译配置下的 FFmpeg 特有标志位。实际上,如果确实遇到了这样的需求,则应该查阅官方文档获取最准确的信息。 为了验证当前使用的 FFmpeg 是否具备 mmap 功能,可以尝试查看帮助手册中的编码器、解码器或者其他组件部分是否有提及相关内容。也可以直接测试带有假设性的参数组合看看是否会抛出未知选项错误提示。 最后提醒一点,即使启用了内存映射技术,也不一定总是能带来性能上的显著提升,这主要看应用场景和个人计算机的具体状况而定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值