Linux环境下的内存管理(2/7)

要想深入理解内存中的堆栈管理机制,孤立地分析并不是一个好方法,因为堆栈内存不是仅靠程序本身来维护的,而是由操作系统、编译器、CPU、物理内存相互配合实现的。

在 Linux 环境下运行的程序,在编译时链接的起始地址都是相同的,而且是一个虚拟地址。Linux 操作系统需要 CPU 内存管理单元的支持才能运行,Linux 内核通过页表和 MMU 硬件来管理内存,完成虚拟地址到物理地址的转换、内存读写权限管理等功能。可执行文件在运行时,加载器将可执行文件中的不同 section 加载到内存中读写权限不同的区域,如代码段、数据段、.bss 段、.rodata 段等。

计算机上运行的程序主要分为两种:操作系统和应用程序。每一个应用程序进程都有 4GB 大小的虚拟地址空间。为了系统的安全稳定,0~4GB 的虚拟地址空间一般为分为两部分:用户空间和内核空间。0~3GB 地址空间给应用程序使用,而操作系统一般运行在 3~4GB 内核空间。通过内存权限管理,应用程序没有权限访问内核空间,只能通过中断或系统调用来访问内核空间,这一定程度上保障了操作系统核心代码的稳定运行。

在 Linux 环境下,虽然所有的程序编译时使用相同的链接地址,但在程序运行时,相同的虚拟地址会通过 MMU 转换,映射到不同的物理内存区域,各个可执行文件被加载到内存不同的物理页上。每个进程都有各自的页表,用来记录各自进程中虚拟地址到物理地址的映射关系。

通过这种地址管理,每个进程都可以独享一份独立的、私有的 3GB 用户空间。编译器在编译程序时,不用考虑每个程序在实际物理内存中的地址分配问题。通过内存读写权限管理,可以保护每个进程的空间不被其他进程破坏,从而保障系统的安全运行。Linux 的内存管理系统会自动帮我们完成虚拟空间的内存到物理内存的映射。

堆内存一般在 BSS 段的后面,随着用户使用 malloc 申请的内存越来越多,对空间不断往高地址增长,栈空间则紧挨着内核空间,ARM 使用的是满递减堆栈,栈指针会从用户空间的高地址往低地址不断增长。在堆栈之间的一片茫茫空间中,还有一块区域叫做 MMAP 区域,动态共享库就是使用这片地址空间的。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_39541632/article/details/132529546