
在 Linux 系统中,物理地址和虚拟地址是操作系统内存管理的重要概念。理解它们对于操作系统、内存管理、以及应用程序开发来说非常关键。以下是对 Linux 物理地址和虚拟地址的详细说明,以及相关的示例。
物理地址是指计算机实际内存(RAM)中的一个具体位置。它是硬件层面上内存的唯一标识,用于直接访问物理内存单元。物理地址由内存控制器直接管理,通常不能被应用程序直接访问。
特点:
虚拟地址是操作系统为每个进程分配的地址空间中的一个位置。每个进程都有自己独立的虚拟地址空间,虚拟地址通过页表映射到物理地址。
特点:
虚拟地址和物理地址之间的映射关系由操作系统的内存管理单元(MMU)负责。

MMU 通过页表将虚拟地址转换为物理地址,页表保存了虚拟地址到物理地址的映射信息。不同的进程可以有相同的虚拟地址,但它们映射到的物理地址可能不同。
页表示例:
假设有一个虚拟地址 0xB8000000,通过页表,它可能被映射到物理地址 0x12000000。这个过程是透明的,应用程序只需要处理虚拟地址,操作系统和硬件负责完成地址转换。
在应用程序中,开发人员通常只与虚拟地址打交道。以下是一个简单的 C 程序示例,演示如何使用虚拟地址访问内存。
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr = (int *)malloc(sizeof(int));
if (ptr == NULL) {
fprintf(stderr, "内存分配失败!\n");
return 1;
}
*ptr = 42;
printf("虚拟地址: %p, 值: %d\n", (void*)ptr, *ptr);
free(ptr);
return 0;
}在这个示例中,malloc() 函数分配了一块内存,并返回该内存块的虚拟地址。该地址在程序的虚拟地址空间中有效,指向一个内存位置。通过打印指针 ptr 的值,可以看到虚拟地址。
物理地址的直接使用通常仅限于操作系统内核或驱动程序开发。在内核编程中,开发人员可以通过一些内核 API 来获取物理地址。例如,通过 virt_to_phys() 函数可以将虚拟地址转换为物理地址。
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
int init_module(void) {
void *vaddr;
unsigned long paddr;
vaddr = kmalloc(4096, GFP_KERNEL);
if (!vaddr) {
printk("内存分配失败\n");
return -ENOMEM;
}
paddr = virt_to_phys(vaddr);
printk("虚拟地址: %p, 物理地址: %lx\n", vaddr, paddr);
kfree(vaddr);
return 0;
}
void cleanup_module(void) {
printk("模块卸载\n");
}
MODULE_LICENSE("GPL");这个内核模块分配了一块内存,并将其虚拟地址转换为物理地址。virt_to_phys() 函数只在内核态有效,用户态程序无法直接调用。
虚拟地址的优点:
物理地址的优点:
物理地址和虚拟地址是 Linux 系统内存管理的重要概念。虚拟地址提供了更灵活和安全的内存管理方式,使得每个进程拥有独立的地址空间。而物理地址则直接映射到实际的内存位置,通常用于内核级别的操作。理解这两个概念及其应用,对于系统编程和操作系统的深入理解非常关键。
作者:不脱发的程序猿。原文:https://handsome-man.blog.csdn.net/article/details/141789714 。原文日期:2024-12-30。转载遵循 CC BY-SA 4.0,保留署名与来源。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。