Linux中, malloc申请的是物理内存还是虚拟内存
在 Linux 系统中,malloc
函数申请的是虚拟内存。
以下是关键点说明:
-
虚拟内存的本质:
- 现代操作系统(包括 Linux)都采用虚拟内存管理机制。每个进程都拥有自己独立的、连续的虚拟地址空间。
malloc
是 C 标准库函数,它在这个进程的用户空间虚拟地址空间中分配一块连续的区域。
-
malloc
的工作层级:malloc
本身是用户空间的库函数。它通常通过以下两种系统调用来向内核申请虚拟内存:brk()
/sbrk()
:用于调整堆(Heap)区域的结束位置,从而扩大或缩小堆空间。这是小内存分配的主要方式。mmap()
:用于创建新的内存映射区域(例如,分配大块内存或匿名映射)。这是大内存分配或特殊需求的主要方式。
- 无论哪种方式,
malloc
最终请求内核在进程的虚拟地址空间中预留一段地址范围。
-
物理内存的分配时机:
- 当
malloc
成功返回一个指针时,它只是为你预留了一段虚拟地址范围。 - 此时,物理内存页通常还没有被实际分配。
- 物理内存的分配是延迟发生的:
- 当你的程序第一次读写这块新分配内存中的某个地址时,CPU 会发现该虚拟地址还没有映射到物理内存(页表项无效)。
- 这会触发一个 缺页中断。
- 内核的缺页中断处理程序被调用:
- 它会找到一个可用的物理内存页帧(Page Frame)。
- 将这个物理页帧映射到进程触发缺页的那个虚拟地址(以及它所在的整个虚拟内存页)。
- 建立或更新页表项(Page Table Entry)。
- 然后,你的程序指令得以继续执行,这次访问就成功了。
- 这就是所谓的 按需分配 或 延迟分配。
- 当
-
内核的角色:
- 内核负责管理整个系统的物理内存资源。
- 内核维护着进程的页表,页表定义了进程虚拟地址空间到物理内存地址的映射关系。
- 当
malloc
通过brk/sbrk
或mmap
请求虚拟内存时,内核更新进程的虚拟内存布局信息(如mm_struct
中的vm_area_struct
链表)。 - 内核的缺页中断处理程序在访问发生时动态地将物理内存页分配给进程的虚拟地址。
总结:
malloc
直接申请的是进程虚拟地址空间中的一段连续虚拟内存。- 物理内存的分配是由内核延迟执行的,发生在程序首次访问该内存区域时(通过缺页中断机制)。
- 内核通过页表管理虚拟地址到物理地址的映射关系。
因此,当你调用 malloc(1024)
成功时,你获得的是 1024 字节的虚拟内存地址。操作系统只保证当你尝试使用这块内存时,会有物理内存(或交换空间)在背后支持它,但物理内存的实际分配发生在你第一次读/写操作的那一刻。