电子产业一站式赋能平台

PCB联盟网

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

Linux物理地址和虚拟地址

[复制链接]

1002

主题

1002

帖子

8854

积分

高级会员

Rank: 5Rank: 5

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

va2mclgvhgp64022998228.gif

va2mclgvhgp64022998228.gif
; V1 ~% c' q6 B  a( Q2 A
点击上方蓝色字体,关注我们. g, `8 S; y9 M$ q6 C2 m, o/ u
) K1 h2 e' a) Q- h
MMU 通过页表将虚拟地址转换为物理地址,页表保存了虚拟地址到物理地址的映射信息。不同的进程可以有相同的虚拟地址,但它们映射到的物理地址可能不同。
$ N. W$ {) _3 Z5 O& \
1 u( O% ~( V9 f% t6 [- Y
  • 页 (Page): 虚拟内存和物理内存被划分为相同大小的块,称为页。: l: O( [# l& ^9 E  U
    常见的页大小为 4 KB。
  • 页表 (Page Table): 页表是一个数据结构,存储了虚拟地址与物理地址的映射。, K* h: m! W" u

    2 m: U2 p2 L$ |9 B3 v$ C4 |5 `页表示例:
    " l' [( @& V6 N* b/ d% k1 b7 F假设有一个虚拟地址 0xB8000000,通过页表,它可能被映射到物理地址 0x12000000。这个过程是透明的,应用程序只需要处理虚拟地址,操作系统和硬件负责完成地址转换。6 c1 v( i$ _3 ]! Z/ a1 q2 `  C
    4* ?* h  j- w  L9 i3 J
    虚拟地址的应用实例
    8 M, T7 a: w/ Z* M2 y! @6 r在应用程序中,开发人员通常只与虚拟地址打交道。以下是一个简单的 C 程序示例,演示如何使用虚拟地址访问内存。4 N" Q# P* K; G; ^+ _/ ~

    % u8 `5 C$ k$ U7 C; m
  • #include #include  int main() {    int *ptr = (int *)malloc(sizeof(int));    if (ptr == NULL) {        fprintf(stderr, "内存分配失败!
    : M  \, q! F( Z5 S) z");        return 1;    }     *ptr = 42;    printf("虚拟地址: %p, 值: %d
    ; z- K4 n) L! S" B  b/ D) t1 B", (void*)ptr, *ptr);     free(ptr);    return 0;}
    1 ]' @2 ?; ], y' J在这个示例中,malloc() 函数分配了一块内存,并返回该内存块的虚拟地址。该地址在程序的虚拟地址空间中有效,指向一个内存位置。通过打印指针 ptr 的值,可以看到虚拟地址。% Q6 N! g3 N5 y( G
    5
    2 X4 a" |0 y# H& z0 e" m! Q+ x物理地址的应用实例
    4 m8 r. {) ^! w8 m9 o6 c) ?0 O物理地址的直接使用通常仅限于操作系统内核或驱动程序开发。在内核编程中,开发人员可以通过一些内核 API 来获取物理地址。例如,通过 virt_to_phys() 函数可以将虚拟地址转换为物理地址。
    , ]8 r6 U9 H" x+ S* n1 p0 S4 r; Z/ \2 `
  • #include #include #include  int init_module(void) {    void *vaddr;    unsigned long paddr;     vaddr = kmalloc(4096, GFP_KERNEL);    if (!vaddr) {        printk("内存分配失败
    ; ^6 N9 {* C4 f6 h/ _0 Z+ L  \" j");        return -ENOMEM;    }     paddr = virt_to_phys(vaddr);    printk("虚拟地址: %p, 物理地址: %lx
    + q+ _5 I; E' e" N. ]", vaddr, paddr);     kfree(vaddr);    return 0;} void cleanup_module(void) {    printk("模块卸载4 r; O. s" k" S) P
    ");} MODULE_LICENSE("GPL");2 N) `% i+ v" E( Y7 P" x' |& [
    这个内核模块分配了一块内存,并将其虚拟地址转换为物理地址。virt_to_phys() 函数只在内核态有效,用户态程序无法直接调用。$ J; I2 }- e' g6 o! X
    6
    & r& y, g& ]. j9 k2 |) q" F) _
    / U7 T4 Z  A) e0 B& f6 T( t, y" u7 V物理地址和虚拟地址的优缺点
    6 `4 n( _; Q/ s虚拟地址的优点* _1 j* L' ?: J5 ^* U* j2 P
  • 每个进程拥有独立的虚拟地址空间,提高了安全性和稳定性。
  • 虚拟地址空间可以大于实际物理内存,通过交换技术(paging),虚拟内存可以被分配给更大的地址空间。
    ' I' K7 y  v) R7 _# \) u" I
    + O: N5 l4 `0 S
    物理地址的优点. O: a/ K7 K+ a) m
  • 直接对应物理内存,访问速度快,无需经过地址转换。
  • 在操作系统内核和驱动程序中,物理地址通常用于直接访问硬件资源。7 \' [  @2 d) U4 y+ M% @* T

    & b) g1 d0 a- c  o) M/ r7 i, f物理地址和虚拟地址是 Linux 系统内存管理的重要概念。虚拟地址提供了更灵活和安全的内存管理方式,使得每个进程拥有独立的地址空间。而物理地址则直接映射到实际的内存位置,通常用于内核级别的操作。理解这两个概念及其应用,对于系统编程和操作系统的深入理解非常关键。
    / W% q! q2 G: E

    eftvajl3jfr64022998328.jpg

    eftvajl3jfr64022998328.jpg

    $ E$ ?& i- R& N& n* O4 ]

    gkgfbkpow1q64022998428.gif

    gkgfbkpow1q64022998428.gif
    3 ?' r: y7 ?: I0 x' }
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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