电子产业一站式赋能平台

PCB联盟网

搜索
查看: 54|回复: 0
收起左侧

Linux物理地址和虚拟地址

[复制链接]

649

主题

649

帖子

4484

积分

四级会员

Rank: 4

积分
4484
发表于 2024-9-14 12:03:00 | 显示全部楼层 |阅读模式

kgpfh2c4fmb64018088727.gif

kgpfh2c4fmb64018088727.gif

7 T' ^! x1 z7 P4 D/ M9 A" l点击上方蓝色字体,关注我们
3 ^" y0 s! }1 X. f0 z( p6 ~9 R8 ^
& B" o* _( x: b# f( U$ mMMU 通过页表将虚拟地址转换为物理地址,页表保存了虚拟地址到物理地址的映射信息。不同的进程可以有相同的虚拟地址,但它们映射到的物理地址可能不同。
" o, i5 g# V' }2 n+ a% Y! S# `) _( i+ i/ _! P' s6 i: m3 I
  • 页 (Page): 虚拟内存和物理内存被划分为相同大小的块,称为页。
      U& Y! G- `- _" _# U# ]常见的页大小为 4 KB。
  • 页表 (Page Table): 页表是一个数据结构,存储了虚拟地址与物理地址的映射。
    * c; Z9 V' M% Z- h+ r, |; ?: [9 z0 N

    5 t# {. S* |2 v1 F$ q, A1 I( F8 P$ N页表示例:; E5 l6 d# D  p. b- ?
    假设有一个虚拟地址 0xB8000000,通过页表,它可能被映射到物理地址 0x12000000。这个过程是透明的,应用程序只需要处理虚拟地址,操作系统和硬件负责完成地址转换。8 l# k* r. j0 `0 ]: U
    4
    8 [" T% c, Y4 |- V" Q) e8 J虚拟地址的应用实例
    # B8 q/ m2 n" z+ B  Q* n5 t在应用程序中,开发人员通常只与虚拟地址打交道。以下是一个简单的 C 程序示例,演示如何使用虚拟地址访问内存。  e  L/ J9 U/ [7 O( a/ d- E5 e
    : u9 m& O- t, b& |4 e
  • #include #include  int main() {    int *ptr = (int *)malloc(sizeof(int));    if (ptr == NULL) {        fprintf(stderr, "内存分配失败!1 q! \, Z+ |* R# _9 k- R' g
    ");        return 1;    }     *ptr = 42;    printf("虚拟地址: %p, 值: %d
    $ U! I  w6 U% I+ M; f", (void*)ptr, *ptr);     free(ptr);    return 0;}& r6 H5 k+ u$ v
    在这个示例中,malloc() 函数分配了一块内存,并返回该内存块的虚拟地址。该地址在程序的虚拟地址空间中有效,指向一个内存位置。通过打印指针 ptr 的值,可以看到虚拟地址。
    # }7 F- T  d8 T0 a$ Q5
    ) N' U5 ~  j8 l1 I/ O1 L. R" j7 V物理地址的应用实例3 W" m% t% L9 I: Q' T
    物理地址的直接使用通常仅限于操作系统内核或驱动程序开发。在内核编程中,开发人员可以通过一些内核 API 来获取物理地址。例如,通过 virt_to_phys() 函数可以将虚拟地址转换为物理地址。: K4 z5 P0 `0 [( j4 y
    / X7 }. Y/ r: Y: H  K
  • #include #include #include  int init_module(void) {    void *vaddr;    unsigned long paddr;     vaddr = kmalloc(4096, GFP_KERNEL);    if (!vaddr) {        printk("内存分配失败
    ' c6 S7 ^5 q1 |/ `7 Z/ j  V");        return -ENOMEM;    }     paddr = virt_to_phys(vaddr);    printk("虚拟地址: %p, 物理地址: %lx
    / m+ m: `* S/ `6 z. N' u+ [", vaddr, paddr);     kfree(vaddr);    return 0;} void cleanup_module(void) {    printk("模块卸载
    . F) J4 U# ^) j+ ?) K$ p, w0 W");} MODULE_LICENSE("GPL");
    8 e' O+ a1 v9 U4 V6 ?. r这个内核模块分配了一块内存,并将其虚拟地址转换为物理地址。virt_to_phys() 函数只在内核态有效,用户态程序无法直接调用。
    . g' S8 o6 a- y: o4 @4 i62 n  k* X9 ?/ S" F2 _: H

    / L5 B1 d( E6 S* a物理地址和虚拟地址的优缺点
    # Y0 I! x% c2 y7 r虚拟地址的优点
    - ^3 e3 e: x, M, ^7 u0 J+ o
  • 每个进程拥有独立的虚拟地址空间,提高了安全性和稳定性。
  • 虚拟地址空间可以大于实际物理内存,通过交换技术(paging),虚拟内存可以被分配给更大的地址空间。
    $ Q0 V1 e# f% C/ Z1 k0 z" l- A

    ) M) a) \  `/ X- X. O- z" n) B物理地址的优点, x/ a: N% [' V
  • 直接对应物理内存,访问速度快,无需经过地址转换。
  • 在操作系统内核和驱动程序中,物理地址通常用于直接访问硬件资源。' [) g" g! s+ }, x

    3 p+ `, T8 j3 L6 N物理地址和虚拟地址是 Linux 系统内存管理的重要概念。虚拟地址提供了更灵活和安全的内存管理方式,使得每个进程拥有独立的地址空间。而物理地址则直接映射到实际的内存位置,通常用于内核级别的操作。理解这两个概念及其应用,对于系统编程和操作系统的深入理解非常关键。
    " ~% l. o7 Q# U, ^  |* R

    0n15zep2ohq64018088828.jpg

    0n15zep2ohq64018088828.jpg

    ' h; L% K5 A/ c

    mzwlumuoh2t64018088928.gif

    mzwlumuoh2t64018088928.gif
    . h9 S7 O* g3 @* ?
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表