在昨天的问题之后,我做了一些研究,我认为我对linux进程内存映射有了更清晰的了解。
我认为我最初混淆的一个原因是对Wikipedia的错误解释,声称堆是数据段的一部分,这显然是错误的。此外,它声称数据段不是只读的,因此与Rodata不同。
但是,我的理解是数据段包含rodata,BSS和数据,任何人都可以确认我的理解吗? (如果专家可以重写维基百科的文章,那就更好了。)
答案 0 :(得分:2)
“细分”是一个相当古老的概念,可追溯到现代页面内存架构未被广泛使用的时代。分段架构迫使内存布局非常严格,而分页内存允许进程拥有许多独立的虚拟内存区域,每个区域都有自己的访问限制。
Linux进程有一个 text (或代码)区域,其中包含可执行文件的代码(从可执行文件的文本部分初始化)和数据< / em>包含运行时数据的区域(从可执行文件的数据, bss 和(可能) rodata 部分初始化)。这些区域(或多或少)对应于旧式文本和数据段。它还有一个堆栈,也可以访问其他内存区域,例如内存映射文件和动态库中的代码。
[文章]声称堆是数据段的一部分,这显然是错误的
这不一定是错的。可以通过扩展数据段(使用brk()
系统调用),或通过创建新的内存区域(使用mmap()
创建匿名映射)或两者的组合来创建堆。由第一个方法创建的堆空间是数据段的一部分,尽管在这种情况下,该文章说明该段具有固定大小是不正确的。
此外,它声称数据段不是只读的,因此与Rodata不同。但是,我的理解是数据段包含rodata,BSS和数据。
这篇文章略显混乱;您无法将段(进程的内存区域)与部分(可执行文件的一部分)进行比较。可以通过将只读数据放在单独的写保护区域而不是可写数据区域来保护只读数据。现代桌面/服务器操作系统将执行此操作(通常通过将文件的rodata部分直接映射到内存中);更简单的系统可能没有写保护存储器的机制,因此更有可能将其放在数据段中。
了解在Linux进程中如何布局内存的好方法是查看/proc/<PID>/maps
文件。这将显示该进程可用的每个区域的虚拟地址范围,访问限制和映射文件(如果有)。
答案 1 :(得分:0)
现代桌面操作系统根本没有细分。记忆有一个扁平的模型。您发现讨论部分的任何内容都指的是二进制可执行格式 - 而不是过程或操作系统。