我在Linux用户空间应用程序中分配了一些内存。但是,这种内存还没有得到物理内存的支持。
为了映射页面,我尝试从区域中的每个页面进行读取,如下所示。但这对我来说并不总是有效的。
以下是我的原始代码:
void Function(void)
{
char *memory;
memory = malloc(4096 * 10);
}
这样分配,虚拟内存还没有映射到物理RAM。
所以我对代码做了如下修改:
void Function(void)
{
char *memory;
volatile uint *accessMemory;
memory = malloc(4096 * 10);
accessMemory = (volatile uint *)memory;
for (i = 0; i < 4096 / 10; i++) {
printf("%X\n", *accessMemory);
accessMemory = (volatile uint *)((uint)accessMemory + 4096);
}
}
但我仍然有同样的问题。我做错了什么?
发布于 2015-06-02 23:54:13
我不太明白你在说什么"Bug“,但是为了确保内存是默认的并且避免了写时复制机制(即当你尝试访问你分配的内存时不会发生页面错误),你应该使用mmap() syscall并将MAP_POPULATE标志传递给它。
例如:
void *addr;
addr = mmap(NULL, 4096 * 10, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
无论如何,当请求大量数据时,malloc()在内部使用mmap() (例如,glibc至少有128 kB -尽管这个值是可调整的)
有关详细信息,请参阅man mmap。
编辑:如果你想改变你的映射的大小,你可以使用mremap()来模拟realloc()调用。请参见man mremap。
但你必须小心使用它:
所以它可能不能完全满足你的需求。在这种情况下,您应该考虑使用多个映射,或者以某种方式预先计算映射应该有多大。
发布于 2015-06-02 23:56:46
你的代码有一个明显的问题,类型转换是一种症状。您为40960个字符分配了空间,但随后尝试访问无符号的409个无符号整数,每个无符号整数分别为4096个。不仅如此,您还可以在执行算术之前强制将指针指向uint -这很可能是一个缩小转换范围,而且肯定是不安全的。
你最好把你的memory
指针声明为你想要使用的类型:
const size_t page_size = 4096; // TODO: get actual value from system
uint *memory;
uint *end;
volatile uint *p;
memory = malloc(page_size * 10 * sizeof *memory);
end = memory + page_size * 10;
for (p = memory; p < end; p += 4096/(sizeof *p))
printf("%X\n", *p);
话虽如此,如果您希望在页面方面工作,最好使用mmap()
;特别是这个选项:
MAP_POPULATE (从Linux2.5.46开始)
为映射填充(故障前)页面表。对于文件映射,这会导致对文件进行预读。以后对映射的访问将不会因为页面错误而被阻止。从Linux2.6.23开始,私有映射才支持MAP_POPULATE。
https://stackoverflow.com/questions/30600114
复制相似问题