可能重复:
mmap()与读取块
我听说(在互联网上读取它)mmap()比顺序IO更快.它是否正确?如果是,那为什么它更快?
mmap() 不按顺序阅读.mmap()具有从盘面本身一样去取read()呢那么mmap()实际上应该比read()文件慢吗?我上面的哪些假设是错误的?
我建了两个程序,一个使用malloc,另一个使用mmap.使用的执行时间mmap远远少于使用malloc.
我知道,例如,当您使用时,mmap请避免对系统进行读/写调用.并且内存访问较少.
但在使用时,还有没有其他原因的优势mmap超过malloc?
非常感谢
我正在尝试编写一个用于在Beaglebone上闪烁LED的C程序.我知道我可以使用sysfs方式......但是我想看看是否可以使用/ dev/mem获得与物理地址空间映射相同的结果.
我有一个头文件,beaglebone_gpio.h,内容如下:
#ifndef _BEAGLEBONE_GPIO_H_
#define _BEAGLEBONE_GPIO_H_
#define GPIO1_START_ADDR 0x4804C000
#define GPIO1_END_ADDR 0x4804DFFF
#define GPIO1_SIZE (GPIO1_END_ADDR - GPIO1_START_ADDR)
#define GPIO_OE 0x134
#define GPIO_SETDATAOUT 0x194
#define GPIO_CLEARDATAOUT 0x190
#define USR0_LED (1<<21)
#define USR1_LED (1<<22)
#define USR2_LED (1<<23)
#define USR3_LED (1<<24)
#endif
Run Code Online (Sandbox Code Playgroud)
然后我有我的C程序,gpiotest.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "beaglebone_gpio.h"
int main(int argc, char *argv[]) {
volatile void *gpio_addr = NULL;
volatile unsigned int *gpio_oe_addr = NULL;
volatile unsigned int *gpio_setdataout_addr = NULL;
volatile unsigned int *gpio_cleardataout_addr …Run Code Online (Sandbox Code Playgroud) 什么限制了内存映射文件的大小?我知道它不能超过最大的连续未分配地址空间块,并且应该有足够的可用磁盘空间.但还有其他限制吗?
我们正在尝试更改嵌入式数据库系统SQLite,使用mmap()而不是通常的read()和write()调用来访问磁盘上的数据库文件.对整个文件使用单个大映射.假设文件足够小,我们可以毫不费力地在虚拟内存中找到空间.
到现在为止还挺好.在许多情况下,使用mmap()似乎比read()和write()快一点.而且在某些情况下要快得多.
调整映射大小以提交扩展数据库文件的写事务似乎是个问题.为了扩展数据库文件,代码可以执行以下操作:
ftruncate(); // extend the database file on disk
munmap(); // unmap the current mapping (it's now too small)
mmap(); // create a new, larger, mapping
Run Code Online (Sandbox Code Playgroud)
然后将新数据复制到新内存映射的末尾.但是,munmap/mmap是不合需要的,因为这意味着下次访问数据库文件的每一页时都会发生次要页面错误,并且系统必须在OS页面缓存中搜索与虚拟内存地址关联的正确帧.换句话说,它会减慢后续数据库读取速度.
在Linux上,我们可以使用非标准的mremap()系统调用而不是munmap()/ mmap()来调整映射的大小.这似乎可以避免次要页面错误.
问题:如何在没有mremap()的其他系统(如OSX)上处理这个问题?
我们目前有两个想法.关于每个问题:
1)创建大于数据库文件的映射.然后,在扩展数据库文件时,只需调用ftruncate()以扩展磁盘上的文件并继续使用相同的映射.
这将是理想的,似乎在实践中起作用.但是,我们在手册页中担心这个警告:
"未指定更改与文件的添加或删除区域对应的页面上的映射的基础文件的大小的效果."
问题:这是我们应该担心的吗?或者在这一点上不合时宜?
2)扩展数据库文件时,使用mmap()的第一个参数来请求与虚拟内存中当前映射之后的数据库文件的新页面对应的映射.有效地扩展初始映射.如果系统无法遵守在第一个之后立即放置新映射的请求,则回退到munmap/mmap.
在实践中,我们发现OSX非常适合以这种方式定位映射,所以这个技巧在那里工作.
问题:如果系统确实在第一个虚拟内存之后立即分配第二个映射,那么使用对munmap()的单个大调用最终是否可以安全地取消映射它们?
关于mmapLinux系统中的实现,我有几个问题似乎没有太多记录:
使用时将文件映射到内存时mmap,如何处理预取此类文件中的数据?
也就是当你从mmaped区域读取数据时会发生什么?这些数据是否已移至L1/L2缓存?它是直接从磁盘缓存中读取的吗?prefetchnta相似的ASM指令是否适用于mmaped区域?
实际mmap通话的开销是多少?它是相对于映射数据量还是常量?
希望有人对此有所了解.提前致谢.
所以,我知道如果你需要一些动态分配的内存,你可以使用malloc().例如,您的程序将可变长度文件读入char [].您事先并不知道制作阵列有多大,因此您需要在运行时分配内存.
我想知道你何时使用mmap().我已经阅读了手册页,说实话,我不明白用例是什么.
有人可以用简单的术语向我解释一个用例吗?提前致谢.
我正在使用一堆大型numpy数组,并且由于这些数组最近开始咀嚼太多内存,我想用numpy.memmap实例替换它们.问题是,我现在必须调整阵列的大小,我最好这样做.这对于普通数组非常有效,但是在memmaps上尝试这一点会抱怨,数据可能会被共享,甚至禁用重新检查也无济于事.
a = np.arange(10)
a.resize(20)
a
>>> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
a = np.memmap('bla.bin', dtype=int)
a
>>> memmap([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
a.resize(20, refcheck=False)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-41-f1546111a7a1> in <module>()
----> 1 a.resize(20, refcheck=False)
ValueError: cannot resize this array: it does not own its data
Run Code Online (Sandbox Code Playgroud)
调整底层mmap缓冲区的大小非常合适.问题是如何将这些更改反映到数组对象.我已经看到了这种解决方法,但不幸的是它没有调整阵列的大小.还有一些关于调整mmaps大小的numpy文档,但它显然不起作用,至少对于1.8.0版本.任何其他想法,如何覆盖内置的大小调整检查?