电子产业一站式赋能平台

PCB联盟网

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

Linux物理地址和虚拟地址

[复制链接]

649

主题

649

帖子

4484

积分

四级会员

Rank: 4

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

yuugl0rqcdb64031921457.gif

yuugl0rqcdb64031921457.gif
3 x/ G. a7 K- a8 }" f4 k5 S' I
点击上方蓝色字体,关注我们
7 v9 P7 ^4 v3 a* h  ]' o" P( g( h
MMU 通过页表将虚拟地址转换为物理地址,页表保存了虚拟地址到物理地址的映射信息。不同的进程可以有相同的虚拟地址,但它们映射到的物理地址可能不同。
% O+ g9 C; I6 B4 t. Y9 t1 W, A8 b! s0 k% H
  • 页 (Page): 虚拟内存和物理内存被划分为相同大小的块,称为页。
    ! G3 D$ a3 I* ~% B/ d) t' P常见的页大小为 4 KB。
  • 页表 (Page Table): 页表是一个数据结构,存储了虚拟地址与物理地址的映射。
    7 _5 y% `# o+ @  [% C) ?0 [

    . p& g% e$ a6 Z' k' E9 G页表示例:: @% d$ G5 _- ^! l
    假设有一个虚拟地址 0xB8000000,通过页表,它可能被映射到物理地址 0x12000000。这个过程是透明的,应用程序只需要处理虚拟地址,操作系统和硬件负责完成地址转换。
    3 Z2 c: j7 m3 T# {: f4
    . k# Q! i1 w8 `2 p0 C6 l# ^虚拟地址的应用实例
    ; t# \  G- X7 l7 A$ X9 C0 f在应用程序中,开发人员通常只与虚拟地址打交道。以下是一个简单的 C 程序示例,演示如何使用虚拟地址访问内存。5 k; B# P9 N$ J! \; U
    $ y" l, `; t# O- {( h4 a" m
  • #include #include  int main() {    int *ptr = (int *)malloc(sizeof(int));    if (ptr == NULL) {        fprintf(stderr, "内存分配失败!" ~2 ^  o( E: T9 D7 z
    ");        return 1;    }     *ptr = 42;    printf("虚拟地址: %p, 值: %d
    " j4 |# r# L8 N9 D  s", (void*)ptr, *ptr);     free(ptr);    return 0;}3 P, A) E, }+ Q! P& K4 A
    在这个示例中,malloc() 函数分配了一块内存,并返回该内存块的虚拟地址。该地址在程序的虚拟地址空间中有效,指向一个内存位置。通过打印指针 ptr 的值,可以看到虚拟地址。
    / I! \8 s7 `2 C; O. X0 y2 I5
    + ~( k5 ]# b+ i4 Q5 [物理地址的应用实例
    # m6 p+ |2 n% |2 `5 [物理地址的直接使用通常仅限于操作系统内核或驱动程序开发。在内核编程中,开发人员可以通过一些内核 API 来获取物理地址。例如,通过 virt_to_phys() 函数可以将虚拟地址转换为物理地址。- Z3 q2 \! y9 O# M0 @

    # j$ k8 X7 a) R. ]$ h1 J: C
  • #include #include #include  int init_module(void) {    void *vaddr;    unsigned long paddr;     vaddr = kmalloc(4096, GFP_KERNEL);    if (!vaddr) {        printk("内存分配失败
    : w, s8 b2 u3 ^& q, m5 f# d");        return -ENOMEM;    }     paddr = virt_to_phys(vaddr);    printk("虚拟地址: %p, 物理地址: %lx
    8 G2 ]7 M* g- |3 K", vaddr, paddr);     kfree(vaddr);    return 0;} void cleanup_module(void) {    printk("模块卸载  `  p6 m0 d9 a" [" Y
    ");} MODULE_LICENSE("GPL");# u5 D, [3 z0 n& R
    这个内核模块分配了一块内存,并将其虚拟地址转换为物理地址。virt_to_phys() 函数只在内核态有效,用户态程序无法直接调用。
    ' M' z& Y  ~9 r( f5 \. K" N6
    9 F1 @$ k8 }& S& J& ?% l
      w" p( J. I& Z: d+ p# I) c物理地址和虚拟地址的优缺点
    9 S. E" `- S- N& i, D虚拟地址的优点- G: d; }+ K- i1 b0 ~
  • 每个进程拥有独立的虚拟地址空间,提高了安全性和稳定性。
  • 虚拟地址空间可以大于实际物理内存,通过交换技术(paging),虚拟内存可以被分配给更大的地址空间。3 q* L: g, Q" R8 y3 k! d7 M
    ( F! m9 l! _8 n1 c+ M8 K8 {
    物理地址的优点- y8 S+ `$ J4 o' S7 @8 A! r
  • 直接对应物理内存,访问速度快,无需经过地址转换。
  • 在操作系统内核和驱动程序中,物理地址通常用于直接访问硬件资源。
      z* u3 L4 o6 H3 _0 M, `7 w. Z
    ( b4 {' R- G# J% p/ ^3 J
    物理地址和虚拟地址是 Linux 系统内存管理的重要概念。虚拟地址提供了更灵活和安全的内存管理方式,使得每个进程拥有独立的地址空间。而物理地址则直接映射到实际的内存位置,通常用于内核级别的操作。理解这两个概念及其应用,对于系统编程和操作系统的深入理解非常关键。5 d: S9 s$ D. L& j. B

    ihb4gth1ceo64031921557.jpg

    ihb4gth1ceo64031921557.jpg
    7 y, _# W/ g% G

    scyq31odnkz64031921657.gif

    scyq31odnkz64031921657.gif
    / a0 g9 ^- b8 h$ B
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

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

    本版积分规则


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