LINUX内存映射问题

LINUX内存映射问题,第1张

Linux的内存模型,一般为:

地址

作用

说明

>=0xc000 0000

内核虚拟存储器

用户代码不可见区域

<0xc000 0000

Stack(用户栈)

ESP指向栈顶

空闲内存

>=0x4000 0000

文件映射

<0x4000 0000

空闲内存

Heap(运行时堆)

通过brk/sbrk系统调用扩大堆,向上增长。

.data、.bss(读写段)

从可执行文件中加载

>=0x0804 8000(0x00008000 for arm linux)

.init、.text、.rodata(只读段)

从可执行文件中加载

<0x0804 8000(0x00008000 for arm linux)

保留区域

运行一个测试程序,观察其结果:

#include <stdio.h>

int main(int argc, char* argv[])

{

int first = 0

int* p0 = malloc(1024)

int* p1 = malloc(1024 * 1024)

int* p2 = malloc(512 * 1024 * 1024 )

int* p3 = malloc(1024 * 1024 * 1024 )

printf("main=%p print=%p\n", main, printf)

printf("first=%p\n", &first)

printf("p0=%p p1=%p p2=%p p3=%p\n", p0, p1, p2, p3)

getchar()

return 0

}

运行后,输出结果为:

main=0x8048404 print=0x8048324

first=0xbfcd1264

p0=0x9253008 p1=0xb7ec0008 p2=0x97ebf008 p3=0x57ebe008

my pc (fc5)输出结果如下:

main=0x80483f4 print=0x8048324

first=0xbf848660

p0=0x9ab2008 p1=0xb7e38008 p2=0x97e37008 p3=(nil)

arm-linux输出如下结果:

main=0x8528 print=0x8404

first=0xbec9fe10

p0=0x11008 p1=0x4005a008 p2=(nil) p3=(nil)

main和print两个函数是代码段(.text)的,其地址符合表一的描述。

first是第一个临时变量,由于在first之前还有一些环境变量,它的值并非0xbfffffff,而是0xbfcd1264,这是正常的。

p0是在堆中分配的,其地址小于0x4000 0000,这也是正常的。

但p1和p2也是在堆中分配的,而其地址竟大于0x4000 0000,与表一描述不符。

原因在于:运行时堆的位置与内存管理算法相关,也就是与malloc的实现相关。关于内存管理算法的问题,我们在后继文章中有详细描述,这里只作简要说明。在glibc实现的内存管理算法中,Malloc小块内存是在小于0x4000 0000的内存中分配的,通过brk/sbrk不断向上扩展,而分配大块内存,malloc直接通过系统调用mmap实现,分配得到的地址在文件映射区,所以其地址大于0x4000 0000。

Linux移植到目标电路板的过程中,有得会建立外设IO内存物理地址到虚拟地址的静态映射,这个映射通过在与电路板对应的map_desc结构体数组中添加新的成员来完成。iotable_init()是最终建立页映射的函数,它通过ACHINE_START、MACHINE_END宏赋值给电路板的map_io())函数。将Linux *** 作系统移植到特定平台上,MACHINE_START(或者DT_MACHINE_START)、MACHINE_END宏之间的定义针对特定电路板而设计,其中的map_io ()成员函数完成IO内存的静态映射。在一个已经移植好 *** 作系统的内核中,驱动工程师可以对非常规内存区域的IO内存(外设控制器寄存器、MCU内部集成的外设控制器寄存器等)依照电路板的资源使用情况添加到map_desc数组中,但是目前该方法已经不值得推荐。

Cache和DMA本身似乎是两个毫不相关的事物。Cache被用作CPU针对内存的缓存,利用程序的空间局部性和时间局部性原理,达到较高的命中率,从而避免CPU每次都必须要与相对慢速的内存交互数据来提高数据的访问速率。DMA可以作为内存与外设之间传输数据的方式,在这种传输方式之下,数据并不需要经过CPU中转。

假设DMA针对内存的目的地址与Cache缓存的对象没有重叠区域,DMA和Cache之间将相安无事。但是,如果DMA的目的地址与Cache所缓存的内存地址访问有重叠,经过DMA *** 作,与Cache缓存对应的内存中的数据已经被修改,而CPU本身并不知道,它仍然认为Cache中的数据就是内存中的数据,那在以后访问Cache映射的内存时,它仍然使用陈旧的Cache数据。这样就会发生Cache与内存之间数据“不一致性”的错误。

内存是一种存储设备,现在一般是ddr

sdram,地址是用来标记内存的数据的。在 *** 作系统中物理内存指实际的ddr

sdram,而虚拟内存指的是在硬盘中的缓存,windows中是页面文件,linux中是swap分区。cpu产生的地址是虚拟地址也可以称作有效地址,而在cpu外地址线上的信号称作实际地址或物理地址。这2类地址有某种对应关系,由 *** 作系统管理。如果是x86架构的话,物理地址和虚拟地址中间还有线性地址的概念。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/6181400.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-17
下一篇2023-03-17

发表评论

登录后才能评论

评论列表(0条)

    保存