Linux的地址空间分布解析 (linux地址空间分布)

在Linux操作系统中,每个进程都有一个独立的地址空间,它描述了进程可以使用的地址范围。了解Linux地址空间分布对于开发和调试Linux程序非常有帮助。本文将介绍Linux地址空间的组成和分配。

Linux地址空间

Linux地址空间是指进程虚拟地址。在64位Linux系统中,地址空间大小为128TB,使用了48位的虚拟地址和16位的“内存段”选择器。地址空间包括以下部分:

1. 内核空间

Linux内核是操作系统的核心部分,它负责管理操作系统的资源和提供系统服务。内核空间是操作系统保留的系统内存空间,用于存放内核相关的数据结构和代码。内核空间的大小在不同的内核版本上可能不同,但通常占据了整个地址空间的下半部分,即0x0000000000000000~0x7fffffffffff。

2. 用户空间

用户空间是进程可以访问的空间,用于存放进程的代码、数据和堆栈等信息。用户空间通常在地址空间的上半部分,即0x0000800000000000~0xffff7fffffffffff,大小为128TB。

用户空间又可以划分为以下几部分:

a. 代码段

代码段用于存放可执行程序的指令。代码段通常是只读的,用于保护程序代码,防止被恶意修改。代码段的地址由可执行文件头部指定。

b. 数据段

数据段用于存放程序的全局变量、静态变量、字面量等数据。数据段的大小取决于程序中定义的全局变量和静态变量的大小。数据段通常是可读可写的。

c. 堆

堆是程序运行期间动态内存分配的区域。堆的大小是可变的,可以通过malloc()和free()等函数进行动态管理。

d. 栈

栈用于存放函数的局部变量和调用参数。栈的大小也是可变的,可以通过栈指针的增减进行动态管理。

3. 共享库空间

共享库是一些可重用的程序代码和数据的,它们可以被多个进程共享。共享库通常存放在地址空间的中间部分,即0x00007f0000000000-0x00007fffffffffff,默认大小是128TB。共享库空间的大小可以通过系统配置进行修改。

地址空间的分配

在Linux中,地址空间是通过动态链接器ld.so来分配的。当一个程序启动时,动态链接器会将程序所依赖的所有共享库加载到共享库空间中。动态链接器通过读取程序的ELF格式的头部信息,将可执行文件的代码段、数据段和堆栈分配到用户空间中。

用户空间的分配是通过虚拟内存管理来实现的。Linux采用了分页内存管理机制,每个进程的地址空间被划分为多个大小相等的页面。在进程访问一个未分配的页面时,操作系统会为该页面分配物理内存,将页面映射到物理内存上,并将页面信息记录在进程的页表中。当进程不需要该页面时,操作系统会将物理内存释放,并将该页面从进程的页表中删除。

地址空间中可以有多个进程共享一个页面。共享页面可以用于进程间通信和内存优化。当一个页面被映射到多个进程中时,它只需要在物理内存中存在一个副本。这种技术被称为”写时复制”。

Linux地址空间是操作系统为进程分配的虚拟地址,包括内核空间、用户空间和共享库空间。地址空间的分配是通过动态链接器和虚拟内存管理机制实现的。了解Linux地址空间分布可以帮助开发和调试Linux程序。

相关问题拓展阅读:

求教64位Linux的内核和用户地址空间

我们都知道,32位的Linux中,0xxBFFFFFFFFF 这3GB是分配给用户空间的

0xCxFFFFFFFFFF 这1GB是分配给内核空间的。对于64位的Linux,用户空间和内核空间的分界线在:0xffffffff。前面的(小的)是用户空间,后面(大的)的是内核空间。

linux 虚拟地址,到底怎么理解

不是仅仅 Linux 是这么设计的,整个现代流行的操作系统都是这么设计的。

应用程序被读入内存后,为了保证系统的统一性,所有的程序都有同样的一套寻址规范。这个寻址就是虚拟地址。这个虚拟雀羡族地址是系统提供转换的,不是程序的工作。

如果系统不提供这个功能,那么应用程序就需要自己去寻找没有被使用的内存,以及还要自己去处理内存容量的问题,而且如果程序调用外部的一些函数库,这些函数库也需要分配内存,这会导致应用程序的设计难度非常大,每个应用程序实际上就是一个操作系统了。多个程序共同运行导致内存使用混乱也很容易出现。

应用程序申请内存,使用的是操作系统的内存分配功能。这样操作系统可以根据实际情况给应用程序内存,程序不需要考虑因为内存位置不同而必须不同编写的难度。而且操作系统还可以提供虚拟内存等等各种方式来扩充内存,这样的内存对于应用程序来说是不需要考虑的,一切都有系统打理。

使用虚拟地址后,对于应用程序来说,他的内存使用不需要考虑其他的程序占用,也不需要考虑内存容量的问题,也不需要考虑内存块位置,函数库的调用也都扔给操作系统打理。这使得应用程序不需要考虑具体如何管理内存,只需要考虑作为应用程序的应用部分。

而且,因为内存是虚拟的,应用程序一些函数调用,操作系统可以把多个应用程序的调用都用同一套数据来处理,这样,既可以节约内存使用(就是启动100个应用程序,也只需要内存里有一套函数库而已),也可以做到外部函数库和应用程序没有直接关联,纯粹是由系统做虚拟地址过渡。

至于为什么 4G ,这是传统+一些兼容的考虑。

以前没有这个技术时,每个程序都可以完全使用整个系统,整个空间是连续的。到了这种虚拟地址的方式后,每个程序还是有自己“独立”的一整套内存地址。但每个程序内存使用量肯定不一样。那么多少内存空间才完全够用呢?当时因为正好使用了 32 位系统。那么就把整个 32 位环境支持的 4G 内存容量作为这个极限。

不过因为内存地址是虚拟的。实际应用程序要派则用内存,是需要先申请的,所以只有程序申请后,真实内存才会被占用。这个 4G 只是在算法上作为极限。

不过因为 4G 也是硬件极限。所以 4G 以外的地址都是不能使用的,这就导致另一个问题,一些硬件有存储器,有些硬件需要存储空间做交互(比如 PCI ,比如各种硬件,比如 AGP 显卡)。这些存储区域怎么处理?

所以,Windows Vista 的 32 位版在 4G 内存的机器上曾经报出只有 3.5G (有的机器甚至只有 3.25G 可以用顷弊)。就是这个问题的解决办法导致的:把硬件的内存用虚拟地址的方式,放到虚拟地址的最后面。这样应用程序调用硬件存储时,可以直接按照内存的方式读写。这样应用程序就很好的统一了存储界面:只有 4G 的内存范围,不存在其他方式的存储调用方式(硬盘需要用读写功能读取到内存后才能处理,而不是直接进行处理)。这样应用程序的开发就很简单,而且整个内存的使用每个程序都一样。不存在各种硬件的原因而不同导致的需要重新设计内存管理算法。操作系统也能根据实际应用程序的需要随时分配数据,也可以根据每个程序的运行情况,区别的提供物理内存或者虚拟的内存。

这么设计更大的一个好处是,硬件环境和应用程序是无关的,中间由操作系统做转换。而且应用程序互相之间也没有影响,就好象整个内存都由他自己一个程序使用一样。

PS:说了半天,我发现我自己也说不清楚其中的缘由……

linux的虚拟地址分为物理地址和虚拟地址 。

Linux系统中的物理存储空间和虚拟存储空间的地址范围分别都是从0x到0xFFFFFFFF,共4GB。

1、物理地址

Linux的物理存储空间布局与处理器相关,详细情况可以从处理器用户手册的存储空间分布表(memory map)相关章节中查到,我这里只列出以下几点注意事项:

1)更大node号n不能大于MAX_NUMNODES-1。

2)MAX_NUMNODES表示系统支持的最多node数。在ARM系统中,Sharp芯罩颤片最多支持16个nodes,其他芯片最多支持4个nodes。

3)numnodes是当前系统中实际的内存node数。

4)在不支持CONFIG_DISCONTIGMEM选项的系统中,只有一个内存node。 5)更大bank号m不能大于NR_BANKS-1。

6)NR_BANKS表示系统中穗戚支持的更大内存bank数,一般等于处理器的RAM片选数。ARM系统中,Sharp芯片最多支持16个banks,其他芯片最多支持8个banks。

2、虚拟存储空间布局

在支持MMU的系统中,当系统做完硬件初始化后就使能MMU功能,这样整个系统就运行在虚拟存储空间中,实现虚拟存储空间到物理存储空间映射功能的是处理器的MMU,而虚拟存储空间与5路存储空间的映射关系则是由Linux内核来管理的。32位系统中物理存储空间占4GB空间,虚拟存储空间同样占4GB空间,Linux把物理空间中实际存在的远远小于4GB的物族败内存空间映射到整个4GB虚拟存储空间中除映射I/O空间之外的全部空间,所以虚拟内存空间远远大于物理内存空间,这就说同一块物理内存可能映射到多处虚拟内存地址空间。

问题相当的复杂,建议参考linux基础篇!

linux地址空间分布的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于linux地址空间分布,Linux的地址空间分布解析,求教64位Linux的内核和用户地址空间,linux 虚拟地址,到底怎么理解的信息别忘了在本站进行查找喔。


数据运维技术 » Linux的地址空间分布解析 (linux地址空间分布)