小文两则
2007年5月14日
2007 在 C 语言中实现面向对象的思考.txt
在 2005 年 10 月写的 rosh 程序中,本来用到的最多的是基于对象的及结构化的方法。而在 2006 年的 rosh 1.08 到 rosh 1.09 的改进中,我使用了具有多态特征的方法。这类似于面向对象编程中的接口的多态性。有关接口,可以研究 Java/C# 中的 interface。我在
C 中实现接口的方法是很简单的:使用一个结构体,其中包含多个函数指针,作为接口的调用器。在实际使用这个结构体时,在知道对象类型的位置先初始化这个结构体,使其包含相应的函数指针。然后将这个结构体传给要使用的函数。这样就有了多态性。而在初始化结构体的做法有点像是工厂模型。工厂模型提供一整套可以配套使用的方法,而这里则是提供一整套函数指针。
C 中实现接口的方法是很简单的:使用一个结构体,其中包含多个函数指针,作为接口的调用器。在实际使用这个结构体时,在知道对象类型的位置先初始化这个结构体,使其包含相应的函数指针。然后将这个结构体传给要使用的函数。这样就有了多态性。而在初始化结构体的做法有点像是工厂模型。工厂模型提供一整套可以配套使用的方法,而这里则是提供一整套函数指针。
这样一来,接口就能比较容易地实现了。但是继承怎么办?如果硬要在 C 语言中模拟 C++ 的继承,恐怕不是一件容易的事,而且反而容易出错。我觉得继承可以用组合来代替,即组合基类的对象和新的成员一起作为子类的成员。而多态仍由接口提供。这样就可以实继承了。
2007 对 NT 磁盘缓存的猜想.txt
读了 Inside Windows 2000,感觉 NT 缓存可能是这样的:
# 每个块 256KB,虚地址空间最多 960MB。
# 每次从磁盘文件向虚拟地址映射一个块。同时将虚拟地址向物理内存映射一个块的大小。
# 每次读写磁盘的时候,一个块成为活动块,读写完毕立即变成不活动块。
# 除了随机访问磁盘的方式外,其他情况块由活动变不活动时立即从物理中去除映射,但并不将虚拟内存中此块的内容删除。
# 当物理内存吃紧时,映射物理块可能会导致其他块至少有一块的物理内存必须被释放(由内存管理器通知它),此时猜想缓存管理器会通过一定的算法计算出需要被替换的物理内存中的块(而不是虚地址中的块)进行释放(释放后可能被换入虚拟内存),然后再次尝试映射。
# 所以有时候看到缓存的物理内存占用变得很大,可能是因为文件是以随机方式被打开的。而当这种情况下物理内存不够时文件缓存中的块可能被替换。但是,这些缓存页是还是存在于其虚空间中的。然后当物理内存足够时,再访问这些缓存页就又能将它们换入。
# 验证1:比如启动一次 Mozilla,关闭,再启动一次,再关闭,并观察 CacheCopy Reads/sec 和 Copy Read Hits %/sec,会发现 Copy Reads/sec 上升后恢复到 0,而 Copy Read Hits %/sec 基本上是 100%。然后运行分配并初始化大量内存的程序(如 hog.vbs,其中就包含一句话 dim a(15000000)),观察 MemoryCache Bytes,会发现它下降。再启动 Mozilla,会发现 Copy Reads/sec 再次上升,说明 Mozilla 的缓存数据还在缓存的虚空间中。
# 验证2:启动一次 Mozilla,关闭,再启动一次,再关闭,应观察到 CacheCopy Reads/sec 上升后恢复到 0,且 Copy Read Hits %/sec 也比较高。然后启动 Sound Engine,用它打开一个 wav 文件,然后再用它的“编辑”菜单里的“与外部文件一起编辑”,打开另一个 wav,选择“接到后面”,此时观察 MemoryCache Bytes,会发现它上升,反复应用“与外部文件一起编辑”功能,直到 Cache Bytes 无法再上升为止。然后关闭 Sound Engine。再启动 Mozilla,会再次发现 Copy Reads/sec 上升到和前一次相当的幅度。这说明 Mozilla 的内容仍在缓存的虚空间中。
# 每个块 256KB,虚地址空间最多 960MB。
# 每次从磁盘文件向虚拟地址映射一个块。同时将虚拟地址向物理内存映射一个块的大小。
# 每次读写磁盘的时候,一个块成为活动块,读写完毕立即变成不活动块。
# 除了随机访问磁盘的方式外,其他情况块由活动变不活动时立即从物理中去除映射,但并不将虚拟内存中此块的内容删除。
# 当物理内存吃紧时,映射物理块可能会导致其他块至少有一块的物理内存必须被释放(由内存管理器通知它),此时猜想缓存管理器会通过一定的算法计算出需要被替换的物理内存中的块(而不是虚地址中的块)进行释放(释放后可能被换入虚拟内存),然后再次尝试映射。
# 所以有时候看到缓存的物理内存占用变得很大,可能是因为文件是以随机方式被打开的。而当这种情况下物理内存不够时文件缓存中的块可能被替换。但是,这些缓存页是还是存在于其虚空间中的。然后当物理内存足够时,再访问这些缓存页就又能将它们换入。
# 验证1:比如启动一次 Mozilla,关闭,再启动一次,再关闭,并观察 CacheCopy Reads/sec 和 Copy Read Hits %/sec,会发现 Copy Reads/sec 上升后恢复到 0,而 Copy Read Hits %/sec 基本上是 100%。然后运行分配并初始化大量内存的程序(如 hog.vbs,其中就包含一句话 dim a(15000000)),观察 MemoryCache Bytes,会发现它下降。再启动 Mozilla,会发现 Copy Reads/sec 再次上升,说明 Mozilla 的缓存数据还在缓存的虚空间中。
# 验证2:启动一次 Mozilla,关闭,再启动一次,再关闭,应观察到 CacheCopy Reads/sec 上升后恢复到 0,且 Copy Read Hits %/sec 也比较高。然后启动 Sound Engine,用它打开一个 wav 文件,然后再用它的“编辑”菜单里的“与外部文件一起编辑”,打开另一个 wav,选择“接到后面”,此时观察 MemoryCache Bytes,会发现它上升,反复应用“与外部文件一起编辑”功能,直到 Cache Bytes 无法再上升为止。然后关闭 Sound Engine。再启动 Mozilla,会再次发现 Copy Reads/sec 上升到和前一次相当的幅度。这说明 Mozilla 的内容仍在缓存的虚空间中。