高端做网站价格,wordpress的文档主题,装修公司手机网站模板,做网站入什么科目目录
写在开头
内存与磁盘的关系
基本关系
磁盘缓存
虚拟内存
节约内存的编程方法
通过DLL文件实现函数共有
通过调用_stdcall来降低文件程序的大小
磁盘的物理结构
结尾
写在开头 本文继续阅读总结《程序是怎样跑起来的》这本书#xff08;作者#xff1a;矢泽…目录
写在开头
内存与磁盘的关系
基本关系
磁盘缓存
虚拟内存
节约内存的编程方法
通过DLL文件实现函数共有
通过调用_stdcall来降低文件程序的大小
磁盘的物理结构
结尾
写在开头 本文继续阅读总结《程序是怎样跑起来的》这本书作者矢泽久雄。前两篇博客介绍了这本书的阅读感受并分别对第一章CPU、第四章内存相关的知识进行了总结。详情见
【计算机组成原理】读书笔记第一期对程序员来说CPU是什么-CSDN博客
【计算机组成原理】读书笔记第二期使用有棱有角的内存_Bossfrank的博客-CSDN博客 本文将介绍本书的第五章内存与磁盘的亲密关系。主要介绍了内存与磁盘的相互关系、节约内存的编程方法和磁盘的物理结构。
内存与磁盘的关系 本文内存主要指主内存即存储CPU中运行的程序指令和数据的区域磁盘主要指硬盘。从存储容量上看内存是高速读取速度上高价价格上磁盘则是低速廉价。
基本关系 磁盘中存储的程序必须要加载到内存中才能运行。在磁盘中保存的原始程序是不能直接运行的。原因负责解析和运行程序内容的CPU需要通过内部程序计数器来指定内存地址才能读出程序详见第一章总结。即使CPU可以直接读出并运行磁盘中保存的程序由于磁盘读取速度慢程序的运行速度也会降低。 程序要加载到内存中才可运行图5-1这是理解内存和磁盘关系的基础。接下来介绍两种机制分别是将内存空间暂时充当磁盘的磁盘缓存和将磁盘空间暂时充当内存的虚拟内存。
磁盘缓存 磁盘缓存disk cache是指把从磁盘中读出的数据存储到内存空间中的方式。通过这样的方式当之后需要读取同一数据时就不用再去读取访问速度缓慢的磁盘空间而是直接从内存即磁盘缓存中把内容读出使用磁盘缓存可以大幅度提高磁盘数据的访问速度。Windows提供了磁盘缓存机制不过随着硬盘访问速度的大幅度改善磁盘缓存的效果没有那么明显了。 虚拟内存 虚拟内存virtual memory是指把磁盘的一部分作为假想内存来使用。通过这一机制当程序的大小略超过内存的剩余空间时也可以运行程序。不过由于CPU只能执行加载到内存中的程序。虚拟内存虽说是把磁盘作为内存的一部分来使用但实际上正在运行的程序部分在这个时间点上是必须存在在内存中的。也就是说为了实现虚拟内存就必须把实际内存也可称为物理内存的内容和磁盘上的虚拟内存的内容进行部分置换swap并同时运行程序。 虚拟内存有分段式和分页式两种介绍如下 分段式虚拟内存把要运行的程序分割成以处理集合及数据集合等为单位的段落然后再以分割后的段落为单位在内存和磁盘之间进行数据置换。 分页式虚拟内存在不考虑程序构造的情况下把运行的程序按照一定大小的页page进行分割并以页为单位在内存和磁盘间进行置换。 在windows中虚拟内存采用分页式。在分页式中把磁盘的内容读出到内存称为Page In把内存的内容写入磁盘称为Page Out。一般情况下Windows 计算机的页的大小是4KB。也就是说把大程序用4KB的页来进行切分并以页为单位放入磁盘虚拟内存或内存中图5-3。 顺道一提在Windows中的控制面板可以查看或变更当前虚拟内存设置搜索”调整Windows的外观和性能“选择”高级“ 做个对比
磁盘缓存虚拟内存定义将近期从磁盘中读出的数据存储到内存空间中。把磁盘的一部分作为假想的内存来使用。目的提高磁盘读取速度。在内存不足时也能运行程序。本质内存假想的磁盘磁盘假想的内存
节约内存的编程方法 虚拟内存是无法从根本上解决内存不足的问题。这是因为使用虚拟内存时发生的Page In 和Page Out 往往伴随着低速的磁盘访问因此在这个过程中应用的运行会变得迟钝起来同时这个机制并不能无限扩展内存空间实际内存的总空间大小不变因此我们在编程时还是要想办法节约内存。
通过DLL文件实现函数共有 DLLDynamic Link Library文件动态链接库文件指在程序运行时可以动态加载库函数和数据的的集合的文件。多个应用可以共有同一个DLL 文件。而通过共有同一个DLL 文件则可以达到节约内存的效果。要想了解动态链接库先要了解静态链接 静态链接在实际开发中不可能将所有代码放在一个源文件中所以会出现多个源文件而且多个源文件之间不是独立的而会存在多种依赖关系如一个源文件可能要调用另一个源文件中定义的函数但是每个源文件都是独立编译的即每个.c文件会形成一个.o文件为了满足前面说的依赖关系则需要将这些源文件产生的目标文件进行链接从而形成一个可以执行的程序。这个链接的过程就是静态链接。 静态链接的局限性内存占用大、更新困难。 例如假设我们编写了一个具有某些处理功能的函数MyFunc()。应用A和应用B都会使用这个函数。在各个应用的运行文件中内置函数MyFunc()此处就是Static Link静态链接后同时运行这两个应用内存中就存在了具有同一函数的两个程序。但这会导致内存的利用效率降低。所以有两个同样的函数还是有点浪费图5-5。 如果采用动态链接库dll文件的方式 可以将函数MyFunc()设置为独立的DLL文件在运行时可以被多个应用共有因此内存中存在的函数MyFunc()的程序只有一个从而提高了内存的利用效率 Windows 的操作系统本身也是多个DLL 文件的集合体。有时在安装新应用时DLL 文件也会被追加。应用则会通过利用这些DLL 文件的功能来运行。像这样之所以要利用多个DLL 文件其中一个原因就是可以节约内存。而且DLL 文件还有一个优点就是更新方便在不变更EXE文件的情况下只通过升级DLL 文件就可以更新。
通过调用_stdcall来降低文件程序的大小 通过调用_stdcall来减小程序文件的方法是用C 语言编写应用时可以利用的高级技巧。不过这一思路应该也可以应用在其他编程语言中。这一方法的核心逻辑是针对栈清理处理的所在方调用方/被调用方。栈清理是指把不需要的数据从接受和传递参数时使用的内存上的栈区域中清理掉。 在C语言中调用函数后需要执行栈清理处理的指令该指令不是由程序记述的而是哎程序编译时由编译器自动附加到程序中的。编译器默认将该处理附加在函数的调用方。
下面举例说明栈清理操作默认附加在函数调用方和被调方在内存中的占用情况 例如在代码清单5-1 中从函数main() 中调用了函数MyFunc()。按照默认设定栈的清理处理会附加在函数main() 这一方。在同一个程序中同样的函数可能会被多次反复调用。而如果是同样的函数栈清理处理的内容也是一样的。由于该处理是在调用函数一方因此就会导致同一处理被反复进行造成了内存的浪费。
// 代码5-1 C语言的函数调用程序示例
// 函数调用方
void main()
{int a;a MyFunc(123, 456);
}
// 被调用方
int MyFunc(int a, int b)
{...
} 将代码清单5-1 中调用函数MyFunc() 的部分用汇编语言来表示就如代码清单5-2 所示。最后1行的处理就是清理处理 // 代码5-2 调用MyFunc() 的部分程序汇编语言 push 1C8h ←将参数 456 ( 1c8h) 存入栈中 push 7Bh ← 将参数123 ( 7Bh) 存入栈中 call LTD15 (MyFunc)(00401014) ←调用MyFunc() 函数 add esp, 8 ←运行栈清理 C 语言通过栈来传递函数的参数。push是往栈中存入数据的指令。32 位CPU 中1 次push 指令可以存储4 个字节的数据。代码5-2中由于使用了两次push指令把两个参数456 和123存入到了栈中因此总的来说就是存储了8字节的数据。通过call指令调用函数MyFunc() 后栈中存储的数据就不再需要了。于是这时就通过add esp, 8 这个指令使存储着栈数据的esp 寄存器B前进8 位设定为指向高8位字节地址来进行数据清理(CPU 中栈中堆积的最高位的数据地址是保存在esp寄存器中的。连续运行两次pop指令可以消除两个存储在栈中的4字节数据而同样的功能也可以通过把esp 的数值加8来实现)。 栈清理处理比起在函数调用方进行在反复被调用的函数一方进行时程序整体要小一些。这时所使用的就是_stdcall。在函数前加上_stdcall就可以把栈清理处理变为在被调用函数一方进行
int _stdcall MyFunc(int a, int b)
{...
} 设置为_stdcall编译后和代码5-2中add esp, 8 同样的处理就会在函数MyFunc() 一方执行。虽然该处理只能节约3个字节add esp, 8 是机器语言的3个字节的程序大小不过在整个程序中还是有效果的图5-7。 磁盘的物理结构 磁盘是通过把其物理表面划分成多个空间来使用的。划分的方式有扇区方式和可变长方式两种。一般的Windows计算机所使用的硬盘和软盘采用的都是扇区方式。 扇区方式将磁盘划分为固定长度的空间。 磁道扇区方式中把磁盘表面分成若干个同心圆的空间就是磁道 扇区把磁道按照固定大小能存储的数据长度相同划分而成的空间就是扇区。 扇区是对磁盘进行物理读写的最小单位。扇区的示意图见图5-8。 可变长方式把磁盘划分为长度可变的空间。 扇区是对磁盘进行物理读写的最小单位。Windows 中使用的磁盘一般1 个扇区是512 字节。不过Windows 在逻辑方面软件方面对磁盘进行读写的单位是扇区的整数倍簇。根据磁盘容量的不同1 簇可以是512 字节1 簇 1 扇区、1KB1 簇 2 扇区、2KB、4KB、8KB、16KB、32KB1 簇 64 扇区。磁盘的容量越大簇的容量也越大。 不管是硬盘还是软盘不同的文件是不能存储在同一个簇中的因此不管是多么小的文件都会占用1 簇的空间。 以簇为单位进行读写时1簇中没有填满的区域会保持不被使用的状态。虽然这看起来是有点浪费不过该机制就是如此规定的所以我们也没有什么好办法。另外如果减少簇的容量磁盘访问次数就会增加就会导致读写文件的时间变长。由于在磁盘表面上扇区之间的分界必要的因此如果簇的容量过小磁盘的整体容量也会减少。扇区和簇的大小是由处理速度和存储容量的平衡来决定的。
结尾 本文总结了磁盘的相关内容介绍了内存和磁盘的关系并通过磁盘缓存和虚拟内存两种机制体现内存和磁盘的密不可分由于内存的有限编程时应该尽可能节约内存本章总结了两种节约内存的编程方法即使用dll动态链接库代替静态链接和通过_stdcall改变栈清理机制的处理方最后在物理层面介绍了磁盘的结构包括扇区和簇的概念。 这篇文章就总结到这里吧下一篇可能重点总结程序从编写到运行的过程相关的内容。除此之外还会进一步更新红队打靶的解析和渗透测试相关的技术分享恳请希望读者们多多支持。