找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3127

积分

0

好友

423

主题
发表于 2 小时前 | 查看: 3| 回复: 0

计算机的核心存储部件是内存和磁盘。存储在磁盘上的程序,必须被加载到内存中后才能运行。CPU通过其内部的程序计数器指定内存地址,进而读取和执行程序指令,因此程序代码必须先驻留在内存中。

程序从磁盘加载到内存并运行示意图

磁盘缓存加速访问

磁盘缓存是一种将磁盘中读取的数据暂存到内存空间的技术。当后续需要再次读取同一份数据时,就不再访问物理磁盘,而是直接从高速的内存缓存中获取。这能显著提升磁盘数据的访问速度。

磁盘缓存数据读取流程示意图

虚拟内存:用磁盘扩展内存

虚拟内存技术允许将磁盘的一部分空间作为扩展内存来使用。这与磁盘缓存(用内存模拟磁盘)正好相反,虚拟内存是用磁盘来模拟内存。

借助虚拟内存,即使在物理内存不足的情况下,也能运行较大的程序。例如,在仅剩5MB物理内存时,理论上可以运行一个10MB的程序。但请记住一个根本原则:CPU只能执行已加载到物理内存中的指令。因此,虚拟内存虽然利用了磁盘空间,但在任一时刻,正在运行的那部分程序代码和数据必须位于物理内存中。为了实现这一点,操作系统需要在物理内存和磁盘上的虚拟内存空间之间,动态地交换程序片段,这个过程称为置换。

虚拟内存主要有分页式和分段式两种实现方式。Windows系统采用分页式。这种方式不考虑程序的逻辑结构,而是将运行中的程序按固定大小的块(称为“页”)进行分割,并以页为单位在内存和磁盘之间进行置换。

  • Page In:将磁盘上的页面数据读入物理内存。
  • Page Out:将物理内存中的页面数据写回磁盘。

虚拟内存分页置换机制示意图

虚拟内存虽然能解决内存不足导致程序无法启动的问题,但由于 Page In 和 Page Out 涉及低速的磁盘读写,频繁的置换会拖慢应用程序的运行速度,造成卡顿。

要从根本上缓解内存压力,最直接的方法是增加物理内存容量。另一种思路是从软件层面优化,减小应用程序的内存占用。

节约内存的编程实践

1. 通过 DLL 文件实现函数共享

DLL(动态链接库)文件包含可在程序运行时动态加载的函数和数据集合。其关键特性在于,多个应用程序可以共享同一个DLL文件,从而避免在内存中重复加载相同的代码,达到节约内存的目的。

未使用DLL时,两个程序在内存中各有一份MyFunc函数

使用DLL后,两个程序共享内存中的同一份MyFunc函数

Windows操作系统本身就是由大量DLL文件构成的集合体,采用这种架构的原因之一就是为了高效利用内存。了解这些底层机制,是深入计算机基础知识体系的重要部分。

2. 使用 _stdcall 调用约定减小程序体积

_stdcall 是“标准调用”(standard call)的缩写。在C语言中,函数调用结束后,需要进行栈清理操作,即清除调用函数时压入栈中的参数数据。这段清理指令并非由程序员编写,而是由编译器在编译时自动添加到程序中。

默认情况下,编译器会将栈清理指令放在函数调用方

函数调用示例(C语言):

// 函数调用方
void main()
{
    int a;
    a = MyFunc(123, 456);
}

// 被调用方
int MyFunc(int a, int b)
{
    ...
}

对应的汇编代码(调用方负责清理):

push 1C8h    ← 将参数 456(=1C8h)存入栈中
push 7Bh     ← 将参数 123(=7Bh)存入栈中
call @LT+15 (MyFunc) (00401014) ← 调用 MyFunc() 函数
add esp, 8   ← 执行栈清理(调用方负责)

如果同一个函数被多次调用,那么在调用方进行栈清理会导致多次重复的清理指令。相比之下,如果让被调用方负责清理,那么无论该函数被调用多少次,清理指令在内存中只存在一份,从而减小了程序文件的总体积。

_stdcall 的作用正是将栈清理的责任转移到被调用函数一方。只需将函数声明改为 int _stdcall MyFunc(int a, int b) 并重新编译,原本在调用方的 add esp, 8 操作就会在 MyFunc 函数内部执行。

调用约定与栈清理责任对比示意图

这种对函数调用和内存管理底层细节的优化,体现了高效编程的思维。

磁盘的物理结构

磁盘在使用前,其物理表面会被划分成多个存储单元。主要的划分方式有扇区方式可变长方式。扇区方式将磁盘划分为固定大小的存储块。

  • 磁道:磁盘盘面上的同心圆轨道。
  • 扇区:将磁道按固定长度划分而成的扇形区域,是磁盘进行物理读写的最小单位。通常一个扇区为512字节。

磁盘磁道与扇区结构示意图

在软件层面,操作系统(如Windows)读写磁盘的逻辑单位是,它是扇区大小的整数倍。簇的大小根据磁盘容量而定,可以是512字节(1扇区)、1KB(2扇区)、2KB、4KB乃至32KB(64扇区)。所有的文件都会占用整数个簇的磁盘空间,这意味着一个1字节的文件也可能实际占用4KB(一个簇)的磁盘空间。

理解从物理扇区到逻辑簇的映射,是掌握文件系统和存储管理的关键。如果你对这类深入解析系统工作原理的内容感兴趣,欢迎在云栈社区与更多开发者交流探讨。




上一篇:彻底搞懂C语言作用域与存储期?一个多文件示例带你通关C23标准
下一篇:扣子2.5云手机与云电脑功能详解:AI智能体如何实现自动化运营
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-10 05:03 , Processed in 0.977913 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表