物理内存和虚拟内存

物理内存和虚拟内存一 物理内存 物理内存是计算机硬件中的重要组成部分 它也被称为 RAM 随机访问存储器 是计算机用来存储和临时处理数据的地方 定义 物理内存是计算机中的一种硬件组件 用于存储数据和程序 以供中央处理单元 CPU 进行访问和处理

大家好,我是讯享网,很高兴认识大家。

一、物理内存

物理内存是计算机硬件中的重要组成部分,它也被称为RAM(随机访问存储器),是计算机用来存储和临时处理数据的地方。

综上,物理内存是计算机系统中的关键组件,它提供了一个快速且易于访问的存储空间,用于存储操作系统、应用程序和数据,以支持计算机的正常运行。它是计算机性能的重要因素之一,内存大小和性能对计算机的整体运行速度和多任务处理能力有重要影响。

二、虚拟内存

虚拟内存是计算机操作系统的一个关键概念,它允许程序访问比物理内存(RAM)更大的地址空间。虚拟内存是一种在物理内存和辅助存储设备(通常是硬盘或固态硬盘)之间的抽象内存层,它有助于提高系统的稳定性、多任务处理能力和程序的运行效率。

综上,虚拟内存是一种操作系统的关键特性,它允许程序访问比物理内存更大的地址空间,并提供了一种灵活的内存管理机制,以提高系统的性能、稳定性和多任务处理能力。虚拟内存的使用使得计算机可以运行更大、更复杂的程序,同时提供了更好的用户体验。

三、虚拟内存和物理内存的区别

虚拟内存和物理内存是计算机内存管理中两个重要的概念,它们在计算机内存管理中扮演不同的角色。虚拟内存允许系统在物理内存不足时继续运行程序,提高了系统的稳定性和多任务处理能力。然而,虚拟内存的访问速度相对较慢,因此物理内存仍然是对于性能关键任务的首选。操作系统负责管理这两种内存,以优化计算机的整体性能。现在对它们进行一些对比和区别:

定义:
物理内存:也称为RAM(随机访问存储器),是计算机的实际硬件内存,用于存储正在运行的程序和数据。它是计算机中的主要内存组件,是CPU直接访问的地方。
虚拟内存:是一种抽象的内存层,通过将数据存储在物理内存和辅助存储设备(通常是硬盘或固态硬盘)之间,扩展了可用内存。它为程序提供了一个假象,好像它们拥有比物理内存更大的地址空间。

容量:
物理内存的容量是硬件限制的,通常以吉字节(GB)或兆字节(MB)为单位。
虚拟内存的容量可以比物理内存大得多,它受到硬盘或固态硬盘的大小限制。

稳定性:
物理内存是易失性存储器,断电或重新启动计算机时,内存中的数据会丢失。
虚拟内存可以持久保存数据,因为它的一部分数据存储在辅助存储设备上,不受电源状态的影响。

速度:
物理内存的访问速度远远快于虚拟内存,因为它位于CPU芯片附近。
虚拟内存的访问速度通常较慢,因为它需要将数据从磁盘加载到物理内存中。

地址空间:
物理内存的地址空间是实际存在的,是硬件物理内存的一部分。
虚拟内存的地址空间是虚拟的,它提供了一个假象,好像程序拥有一个更大的内存地址空间。

管理:
物理内存的管理通常由操作系统和硬件控制,用于分配、回收和保护内存区域。
虚拟内存的管理也由操作系统控制,包括页面交换、地址映射和数据的动态加载和卸载。

多任务处理:
物理内存支持多任务处理,但受到物理内存容量的限制。
虚拟内存扩展了多任务处理的潜力,因为它允许操作系统将多个程序的数据存储在辅助存储设备上,只加载正在运行的程序的部分数据到物理内存。

效率:
物理内存访问速度更快,但容量有限。
虚拟内存提供了更大的容量,但访问速度相对较慢。

四、linux内核里的物理内存和虚拟内存

Linux内核中有多种方式可以用于在内核模块或驱动程序中申请物理内存和虚拟内存。在内核开发中,内存的管理和分配通常较为复杂,需要根据具体的驱动程序或内核模块的需求来选择适当的方式和函数。此外,内核内存分配可能会受到一些约束和安全性考虑,因此需要小心操作。如下是物理内存和虚拟内存的一些相关函数。

1、kmalloc() 和 kfree() 函数:
void* kmalloc(size_t size, gfp_t flags) 函数用于在内核中分配一块指定大小的物理内存。gfp_t 参数是用于设置内存分配的标志,例如,GFP_KERNEL 表示在内核上下文中分配内存。
void kfree(void* ptr) 函数用于释放先前由 kmalloc() 分配的内存。
示例代码:

#include <linux/slab.h> void* ptr = kmalloc(1024, GFP_KERNEL); // 分配 1024 字节的内核内存 kfree(ptr); // 释放内存 

讯享网

2、vmalloc() 和 vfree() 函数:
void* vmalloc(unsigned long size) 函数用于在内核中分配大块虚拟内存,通常用于申请大量物理内存,因为物理内存可能不够大。
void vfree(void* addr) 函数用于释放由 vmalloc() 分配的虚拟内存。
示例代码:

讯享网#include <linux/vmalloc.h> void* ptr = vmalloc(4096 * 1024); // 分配 4MB 的虚拟内存 vfree(ptr); // 释放虚拟内存 

3、get_free_pages() 和 free_pages() 函数:
unsigned long get_free_pages(gfp_t flags, unsigned int order) 函数用于分配一页或多页的物理内存,并返回页框的地址。
void free_pages(unsigned long addr, unsigned int order) 函数用于释放先前由 get_free_pages() 分配的内存。
示例代码:

#include <linux/gfp.h> unsigned long page = get_free_pages(GFP_KERNEL, 1); // 分配一页物理内存 free_pages(page, 1); // 释放内存 

4、ioremap() 和 iounmap() 函数:
void* ioremap(resource_size_t offset, unsigned long size) 函数用于在内核中映射I/O内存地址,以便进行I/O操作。
void iounmap(void* addr) 函数用于解除I/O内存的映射。
示例代码:

讯享网#include <linux/ioport.h> void* mapped_addr = ioremap(0x1000, 4096); // 映射I/O内存 iounmap(mapped_addr); // 解除映射 

五、linux内核里相关内存申请函数的大致原理

(1)kmalloc() 函数原理:
内存池初始化:
在Linux内核启动时,内存池(memory pool)会被初始化。这个内存池由一组物理内存块组成,通常是页面大小的倍数。这些物理内存块被划分成不同的大小类别,以便适应不同大小的内存分配请求。

(2)kfree() 函数原理:
内存释放请求:
当内核代码中的某个部分不再需要一个先前通过 kmalloc() 分配的内存块时,它会调用 kfree(void* ptr) 函数,其中 ptr 是指向要释放的内存块的指针。


讯享网

(1)vmalloc() 函数原理:
虚拟地址空间分配:
当内核代码中的某个部分需要分配大块虚拟内存时,它会调用 vmalloc(unsigned long size) 函数,其中 size 参数表示要分配的虚拟内存的大小。vmalloc() 函数在内核的虚拟地址空间中寻找足够大的、未使用的连续地址范围。

(2)vfree() 函数原理:
虚拟内存释放请求:
当内核代码不再需要一个通过 vmalloc() 分配的虚拟内存块时,它会调用 vfree(void* addr) 函数,其中 addr 参数是指向要释放的虚拟内存的指针。

(1)get_free_pages() 函数原理:
内存池初始化:
在Linux内核启动时,内存池(memory pool)会被初始化。这个内存池包含了系统中的所有物理内存页。通常,内核会将物理内存划分成不同的区域,以便更有效地管理内存分配。内存池中的每个页面都有一个状态,用于表示是否已经分配。

(2)free_pages() 函数原理:
内存释放请求:
当内核代码不再需要通过 get_free_pages() 分配的物理页面块时,它会调用 free_pages(unsigned long addr, unsigned int order) 函数,其中 addr 参数是指向要释放的物理页面块的起始物理地址,而 order 参数是与分配时使用的 order 参数相同,用于指示要释放的页面数量。

(1)ioremap() 函数原理:
映射请求:
当内核代码需要与设备寄存器进行交互,或者需要访问与设备相关的内存映射寄存器时,它会调用 ioremap(resource_size_t offset, unsigned long size) 函数。其中,offset 参数表示要映射的I/O内存地址的偏移量,而 size 参数表示要映射的地址范围的大小。

(2)iounmap() 函数原理:
解除映射请求:
当内核不再需要与设备的I/O内存映射进行交互时,或者在模块卸载时,它会调用 iounmap(void* addr) 函数,其中 addr 参数是通过 ioremap() 返回的虚拟地址。

(1)内存类型:
kmalloc() 分配物理内存:kmalloc() 函数分配的内存是物理内存,这意味着它在物理RAM中存在。这种分配方式通常用于需要直接访问硬件设备或需要分配小块内存的情况。
vmalloc() 分配虚拟内存:vmalloc() 函数分配的内存是虚拟内存,它可能不直接对应物理内存。这种分配方式通常用于需要大块连续内存的情况,因为物理内存可能不足以满足这些需求。

(2)分配大小:
kmalloc() 适用于相对较小的内存分配:kmalloc() 主要用于分配小块内存,通常用于几百字节到几千字节的范围。
vmalloc() 适用于较大的内存分配:vmalloc() 适用于需要分配大量内存的情况,通常用于分配大于几千字节的内存块,甚至可以分配多兆字节的内存。

(3)内存分布:
kmalloc() 分配的内存通常位于内核的高端内存区域,这些内存块在物理地址上是连续的。这使得 kmalloc() 分配的内存非常适合直接与硬件设备交互。
vmalloc() 分配的内存则通常位于虚拟地址空间中,并且不一定连续。因此,它适用于需要大量内存但不需要物理连续性的情况。

(4)分配效率:
kmalloc() 在分配和释放小块内存时通常更高效,因为它不需要复杂的虚拟内存管理和分页机制。
vmalloc() 在分配大块内存时可能会引入一些额外的开销,因为它需要更复杂的虚拟内存管理和分页机制来处理大内存块的映射和分页表项。

释放的内存类型: kfree() 释放的是物理内存,也就是真实的硬件RAM。这意味着通过 kfree() 释放的内存会立即回归到系统的可用物理内存池中。

参数: kfree() 接收一个指向要释放内存块的指针作为参数。

内存管理: kfree() 主要用于管理物理内存的分配和释放,它不涉及虚拟内存的映射或管理。

释放的内存类型: vfree() 释放的是虚拟内存,这种内存通常不直接映射到物理RAM。虚拟内存可能会通过分页机制与物理内存交互,但它在虚拟地址空间中占据一定的位置。

参数: vfree() 接收一个指向要释放虚拟内存的指针作为参数。

内存管理: vfree() 主要用于管理虚拟内存的分配和释放,它涉及到虚拟地址空间的管理,包括映射和分页表项的更新。

(1)虚拟内存映射: 在典型的操作系统中,包括Linux,虚拟内存被用于将进程的地址空间抽象成一系列虚拟页面。这些虚拟页面可以映射到物理RAM,也可以映射到磁盘上的交换空间。虚拟内存系统负责管理这些映射。

(2)分页系统: 虚拟内存系统通常使用分页机制,将虚拟页面映射到物理页面。这意味着虚拟内存页的内容可能会被分割成多个物理页面,或者一个虚拟页面可能映射到磁盘上的某个位置。

(3)页表管理: 操作系统通过页表来跟踪虚拟内存页和物理内存页之间的映射关系。每个进程都有自己的页表,用于将虚拟地址转换为物理地址。这意味着虚拟内存页的地址可能与物理RAM地址不同。

(4)内存分配的灵活性: vmalloc() 分配的虚拟内存通常是连续的,但不一定与物理内存页对齐。因此,它们可能会跨越多个物理页面。这使得内核可以更加灵活地管理虚拟内存,不受物理内存的限制。

综上,虚拟内存系统提供了对内存的抽象和管理,允许操作系统将虚拟内存页映射到物理内存页,也可以映射到磁盘上的交换空间。这种抽象和管理机制使得内核可以更灵活地管理内存,但也增加了内存管理的复杂性。因此,虚拟内存页的虚拟地址通常不直接映射到物理RAM地址上。

小讯
上一篇 2025-03-14 16:21
下一篇 2025-01-15 18:23

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/66429.html