0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

探讨Linux操作系统虚拟内存和物理内存的关系

电子设计 来源:TOMORROW 星辰 作者:TOMORROW 星辰 2020-12-10 16:12 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

为了高效、准确测试出该系统下,单个进程能够申请到的最大虚存空间,所以编写了一个Linux的测试程序。因为 64 位真的是个很可怕的数字,所以程序在申请内存空间时,先申请较大的内存块(100G),直到没有这么大的内存块,然后申请上次能申请到的内存块的一半。重复以上步骤,直到内存块变得足够小(小于 100Byte)。然后结束申请内存。代码如下:

#include
#define SZ_100G (50*2147483648)  //100GB 的字节数

int main()
{
	int *p[1000000];//存放申请内存块的指针以备释放
	int *ptem;
	long long int block_sz,total_sz=0;
	int i,j;
	char c='c';

	printf("pid=%d\n",getpid());
	getchar();

	block_sz=SZ_100G;
	for(i=0;;i++)
	{
		printf("i=%d\n",i);
		p[i]=(int *)malloc(block_sz*sizeof(char));
		if(NULL==p[i])//当所申请的内存块不成功时,把内存块大小减半重新申请
		{
			block_sz=block_sz/2;
			p[i]=(int *)malloc(block_sz*sizeof(char));
		}
		total_sz=total_sz+block_sz;//累加所申请到的内存块

		if(block_sz<100)//当内存块小于 100 个字节时结束内存申请
			break;
	}
	getchar();

	ptem=p[0];
	for(j=0;;j++)
	{
		if(0==j%1000)
			c=getchar();
		if('e'==c)
			break;

		*(ptem+=(2*1024*1024))=c;
	}

	for(;i>=0;i--)//释放所有内存块
		free(p[i]);

	printf("total_sz=%ldByte\n",total_sz);
	

	return 0;
}

在终端 1 编译运行上面代码。
运行后,先在另一个终端(终端 2)执行:

cat /proc/6674/status

查看该进程的 status 文件如下图图一所示:

终端 1 终端 2

图一

对于 status 文件,本文只会关注以下几个参数:

VmPeak(进程所占用的虚存空间最大值)

VmRSS(进程正在占用物理内存大小)

VmSwap(进程占用交换区大小)

然后回车开始申请内存,当终端停止输出数字时,再次在终端 2 执行:

cat /proc/6674/status

得到下图图二输出:

终端 1 终端 2

图二

对比图一和图二中的 VmPeak:

137438953320K – 12044K = 140737475866624 Byte

= 111 1111 1111 1111 1111 1111 0100 0001 0111 0000 0000 0000(B) Byte

是的,如果你没有眼花,你数到上面得到的是一个 47 位!!!!二进制数。

47 位什么概念?大概是 128TB = 128*1024GB !!! (试问现在谁的个人电脑有这么大的硬盘??更不要说内存)

一个进程能够申请到这么恐怖的内存空间?这不但超过了物理内存、超过了物理内存+交换区、还超过了硬盘大小啊。这不科学啊。

但是从 status 读出来的数据错不了的。

首先,虚拟内存,顾名思义,虚拟的、并不是事实上存在,在一个进程的虚存空间里,只存在进程自己和系统内核,而不存在其他进程。这是为了方便编程和提高物理内存利用率而创造出来的一种机制(在过去内存是很贵的)。虚拟内存中对应着的是逻辑地址,逻辑地址通过操作系统和硬件的配合映射到物理内存上。(这里就不在多说虚拟内存的定义。如果把段页式内存管理机制理解后,虚拟内存也就理解了。关于段页式内存管理介绍可参考:深入理解操作系统之——分页式存储管理,深入理解操作系统之——段页式存储器管理。)

其二,交换区,实际上就是物理内存不够用时,虚存空间的数据就必须映射到交换区上。

那么单个进程所能申请的最大虚存空间理应不会超过物理内存和交换区的和。然而实际却是超过那么多。

然后,网上查阅相关资料,msdn 上看到了相关解释。

传送门:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/virtual-address-spaces

该文章介绍到,Windows 32 系统下,虚拟内存中,用户空间占用了低地址 2G 的空间,系统内核占用了高地址 2G 空间。总共虚存空间就是 2^32Byte。

pIYBAF_R18aAbdkcAAAjG143L2o351.png

图三

那么 64 位系统中,就系统而言,总共的虚存空间应当是 2^64Byte?

在该文章下面还有 Windows 64 位系统的虚存空间介绍,如下图图四所示。从图中看到用户虚存空间 8TB+系统空间 248TB=256TB=2^48 Byte ,这个数字似乎和上面所测得的单个进程能够申请到的最大虚存空间的数字有点接近了。

pIYBAF_R182AHv1KAAA9UJVQds8012.png

图四

注意看图四,还可以发现 64 位系统中还有很大很大的虚存空间保留没有被使用的。从这个出发继续查阅资料,然后找到了关于目前 64 位 CPU 的相关说明。由于目前还远远用不到 64 位那么大的空间,所以 AMD 64 位 CPU 目前只用了 48 位的寻址。而 Intel 的 64 位 CPU 是和 AMD 交叉授权,所以 Intel 64CPU 也同样只采用 48 位寻址。所以图三的保留空间就得到了解释。

再回到原先的问题,现在知道了就 64 位系统而言,虚拟内存空间是可以达到 2^48Byte 那么大的,参考 Windows 64 位系统虚存空间结构,可以猜测Linux 64 位系统下,用户虚存空间和系统内核虚存空间分布和 Windows 是相似的,只是两者大小比例有所差别。(因为找了很久,没有找到Linux的官方文档说明,只找到很旧的、32 位。所以不能提供准确的参考,如果有读者找到,希望可以告诉作者一下补上)。

不过,到现在,还有问题没有解决,为什么所申请的虚存空间会比物理内存与交换区的和大?

现在回到一开始没有运行完的程序,在终端 1 回车继续运行程序,程序接着会对所申请到的第一个 100G 内存块每隔 2M 空间进行写操作,每回车一次,会写 1000 次。回车几次后,在终端 2 再执行:

cat /proc/6674/status

得到下图图五:

图五

由图五可以看到正在使用的物理内存 VmRSS 变小了,正在使用的交换区空间 VmSwap 迅速增大。但是两者之和是在一直增加的,这就说明,申请到的虚拟内存在未被使用之前,它只是一个数字,并没有实际的物理内存和交换区与之相对应。当对虚存进行写操作时,系统就会逐步分配物理内存,而物理内存的数据又会可能被系统调到交换区。现在问题逐渐明了了。

如果我不停地对虚存空间进行写操作会怎样,为了解决疑惑,在终端 1 不停回车,偶尔在终端 2 中查看 status 文件中的状态,写到一定程度后,终端 1 出现了

[1]    7893 killed     a.out

如图六所示:

图六

在进程结束之前查看到的 status 文件显示 VmRSS+VmSwap 约等 1.8G,加上系统占用和其他进程占用,那么说此时物理内存和交换区已经接近极限了。再继续运行写的时候,操作系统为了系统的正常运行选择把这个进程杀死了。那么所有的疑问也解决了。

系统所允许的申请的虚存空间是可以超过物理内存与交换区的和的。但是当进程所占用的物理内存加上交换区影响到了系统的正常运行就会被系统杀死。
编辑:hfy

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11628

    浏览量

    218015
  • 操作系统
    +关注

    关注

    37

    文章

    7329

    浏览量

    128653
  • 物理内存
    +关注

    关注

    0

    文章

    11

    浏览量

    8643
  • 虚拟内存
    +关注

    关注

    0

    文章

    79

    浏览量

    8415
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux Swap交换空间详解:Android编译内存不足?这样扩充立竿见影

        在  Linux  系统使用过程中,你是否遇到过  “ 内存不足 ”  的报错?比如编译  Android  源码时,明明按教程操作,却因
    的头像 发表于 12-06 08:10 3292次阅读

    FLASH中的代码是如何得到运行的呢

    指令的地址。正常情况下自动加“4”,遇到分支跳转的时候,由跳转指令设置值。那么指针是什么?指针是一个变量的地址,在含有操作系统(比如Linux、Windows)即硬件层面含有内存管理单元(MMU)的情况下,指针是
    发表于 12-04 08:06

    单片机的操作系统

    Linux网络协议栈和文件系统(如JFFS2),但实时性较弱,需外扩存储器。 ‌ ‌ VxWorks ‌:高效实时操作系统,广泛应用于通信、军事等领域,支持自定义硬件模块。 ‌ 其他选择 ‌ Keil
    发表于 11-14 06:18

    Jtti Linux操作系统最常见的10大优势

    Linux操作系统的十大优势 Linux操作系统作为一种开源、自由的系统,已经广泛应用于个人计算机、服务器、嵌入式设备等多个领域。它的多样化
    的头像 发表于 11-06 15:32 129次阅读

    Perforce QAC 2025.2版本更新:虚拟内存优化、100%覆盖CERT C规则、CI构建性能提升等

    【产品更新】Perforce QAC更新至2025.2版本,安装路径和许可证都有变化!重点:虚拟内存占用降低、100%覆盖CERT C规则,C23支持增强、CI构建性能提升等。建议尽快评估升级。
    的头像 发表于 09-09 14:40 439次阅读
    Perforce QAC 2025.2版本更新:<b class='flag-5'>虚拟内存</b>优化、100%覆盖CERT C规则、CI构建性能提升等

    golang内存分配

    内存碎片. 线程拥有一定的 cache, 可用于无锁分配. 同时 Go 对于 GC 后回收的内存页, 并不是马上归还给操作系统, 而是会延迟归还, 用于满足未来的内存需求.   
    的头像 发表于 03-31 15:00 387次阅读
    golang<b class='flag-5'>内存</b>分配

    快速搞懂C语言程序内存分区!

    在程序运行过程中,操作系统会根据程序的需要,将内存划分为多个功能不同的区段,以便更高效地管理内存资源和确保程序的稳定运行。不同的内存区段负责存储不同类型的数据和代码,涵盖了从程序指令、
    的头像 发表于 03-14 17:37 1341次阅读
    快速搞懂C语言程序<b class='flag-5'>内存</b>分区!

    hyper v 内存,hyper v 内存设置的操作步骤和方法是什么?

    造成资源浪费,影响宿主机及其他虚拟机的性能。因此,掌握Hyper-V内存设置的操作步骤和方法,对于高效使用虚拟机十分关键。下面就为大家详细介绍。    Windows
    的头像 发表于 01-24 15:22 1107次阅读
    hyper v <b class='flag-5'>内存</b>,hyper v <b class='flag-5'>内存</b>设置的<b class='flag-5'>操作</b>步骤和方法是什么?

    hyper 内存,Hyper内存:如何监控与优化hyper-v虚拟机的内存使用

    :如何监控与优化hyper-v虚拟机的内存使用。    在虚拟化环境中,合理监控和优化Hyper-V虚拟机的内存使用对于提升性能和资源利用率
    的头像 发表于 01-24 14:15 1686次阅读
    hyper <b class='flag-5'>内存</b>,Hyper<b class='flag-5'>内存</b>:如何监控与优化hyper-v<b class='flag-5'>虚拟</b>机的<b class='flag-5'>内存</b>使用

    hyper内存条,hyper-v 添加虚拟机还需要硬盘吗

    机管理程序,能在Windows系统的计算机上创建虚拟机,让一台物理计算机可同时运行多个操作系统及应用程序。    相关组件,主机:运行虚拟
    的头像 发表于 01-24 14:01 707次阅读
    hyper<b class='flag-5'>内存</b>条,hyper-v 添加<b class='flag-5'>虚拟</b>机还需要硬盘吗

    使用DevEco Studio高效解决鸿蒙原生应用内存问题

    在鸿蒙原生应用开发过程中,可能由于种种原因导致应用内存未被正常地使用或者归还至操作系统,从而引发内存异常占用、内存泄漏等问题,最终导致应用卡顿甚至崩溃,严重影响用户体验。
    的头像 发表于 01-16 14:44 1183次阅读

    如何使用DevEco Studio性能调优工具Profiler定位应用内存问题

    鸿蒙应用开发过程中,可能由于种种原因导致应用内存未被正的使用或者归还至操作系统,从而引发内存异常占用、内存泄漏等问题,最终导致应用卡顿甚至崩溃,严重影响用户体验。
    的头像 发表于 01-16 14:40 2531次阅读
    如何使用DevEco Studio性能调优工具Profiler定位应用<b class='flag-5'>内存</b>问题

    Linux服务器卡顿救星之一招释放Cache内存

    为了加速操作和减少磁盘I/O,内核通常会尽可能多地缓存内存,这部分内存就是Cache Memory(缓存内存)。根据设计,包含缓存数据的页面可以按需重新用于其他用途(例如,应用程序)。
    的头像 发表于 01-16 10:04 2165次阅读

    deepin操作系统介绍

    希望从自己的能力和对桌面操作系统的理解,能给 Linux 的用户与开发者更多的选择。我们也相信 deepin 能够得到更多用户的认可与喜爱,成为开源世界的最佳选择。  一、 deepin 操作系统 先说
    的头像 发表于 12-23 09:08 3233次阅读
    deepin<b class='flag-5'>操作系统</b>介绍

    2024中国操作系统大会盛大启幕

    2024 中国操作系统大会在北京中国大饭店盛大启幕。作为操作系统行业高规格的年度盛会和信息技术应用创新产业的风向标,大会已迈入第五届。本届大会以“创变·求真”为主题,旨在探讨以生成式 AI 为代表的
    的头像 发表于 12-11 14:36 793次阅读