在VOS应用中,VM区域经常被用作可共享的地址空间。这是一种允许多个进程访问同一组地址的非常有效的方式。主要的缺点是,由于VOS的虚拟内存限制,空间被限制在2GB以下,这种使用方式削减了虚拟机可用于其他用途的空间。
通过将地址映射到二进制文件上并通过文件I/O操作访问这些地址,也可以通过文件系统共享地址空间。这样就消除了虚拟机区域大小的限制,释放了原本专用的虚拟机。它还可以通过区域锁定进行协调,但比直接访问共享虚拟机要贵得多,特别是在涉及实际磁盘I/O的情况下。
Posix应用程序有时会为此使用二进制模式的流文件,通过ftruncate(用于其扩展EOF位置的能力)建立所需的地址空间大小,然后定位到文件内的区域,从这些区域读取或写入数据。这样,文件作为地址空间的后备存储,进程使用fseek/fread/fwrite等面向文件的接口共享空间。
在64位流文件(在17.2版中引入)之前,这在VOS上可能是非常昂贵的,因为普通的流文件不可能是稀疏的,而扩展EOF涉及到显式分配和写入二进制零的块。例如,如果所需的地址空间是2GB,那么VOS将需要524,288个磁盘存储块,即使只有一小部分存储块可能包含二进制零以外的值。有了64位流文件,这些类型的应用程序现在可以在VOS上有效地运行,只需要实际需要的磁盘空间。Posix应用程序在为大文件意识构建时,会自动获得64位流文件的好处;你应该这样做才能获得这些性能优势,即使文件预计不会增长到2GB以上。参见OpenVOS POSIX.1参考手册,R502,"将现有应用程序移植到64位流文件环境"以获取更多信息)。
在原生的VOS应用程序中,即那些使用s$接口的应用程序中,也可以类似地使用文件支持的共享地址空间。VOS提供了一些功能,在使用这种技术时可以大大减少磁盘I/O,基本上使CPU的使用成为主要成本。在17.2版中引入了稀疏的64位流文件,使得这种共享地址空间的方法更具吸引力。
存储器驻地和RAM文件
内存常驻文件是通过set_open_options命令来识别的。磁盘缓存的一个可设置的部分被保留给内存常驻文件。根据可用的物理内存和缓存的其他用途,这部分容量可以达到9-10GB。内存常驻文件块一旦进入缓存,只要总数不超过缓存的这部分,就不会引起后续的磁盘读取。如果超过了,那么最近引用的块就会保留这个优势。
RAM文件是包含非持久性数据的文件,如果文件中包含的数据在应用程序使用完毕后不需要提交到磁盘上,那么RAM文件就很有用。你可以使用set_ram_file命令,但任何调用s$delete_file_on_close的文件从那时起就会自动被视为RAM文件。
虽然内存驻留文件不会招致后续的磁盘读取,但仍然会定期写入块,而且缓存中允许修改的块数与其他文件一样受到限制。修改块限制防止了当文件关闭或刷新时可能需要写入数百万个块的情况--一个4GB的文件占用了一百万个块。这种限制可能会减慢一个应用程序的速度,因为它修改数据的速度比写入数据的速度快。RAM文件避免了这种类型的节流,因为它们的数据永远不需要写入磁盘,即使是在文件被停用的情况下。
使用内存常驻RAM文件提供了一个在缓存内存中的地址空间,避免了大部分的磁盘I/O,这个地址空间只受限于缓存大小,而缓存大小又是基于可用的物理内存,而不是虚拟内存(缓存管理器共享虚拟机地址来访问物理内存)。注意:一个基于文件的地址空间可以增长到512GB,但当大于缓存的内存常驻部分时,就会失去I/O优势,至少对于那些最近没有被引用的块来说是如此。
例子
流文件的内容可以使用s$seq_position与面向字节的操作码进行访问,然后使用s$read_raw/s$write_raw进行检查或修改。64位的流文件可以达到512GB,除了文件中被使用的区域外,不需要任何可观的磁盘空间,即设置为非零。
例如:
create_file scratch -organization stream64 -extent_size 256。
这将创建一个名为"scratch"的DAE-256文件。
set_ram_file scratch
这使得这个文件可以无限制地访问缓存,避免任何与修改块数有关的节流,并且完全避免磁盘写入,除非是在后台或缓存耗尽而需要其他用途时。这也可以通过s$set_ram_file进行编程。当最后一个打开者关闭文件时,缓存中的数据会被丢弃,永远不会引起磁盘写入。当使用这个命令时,文件必须是空的。
set_open_options scratch -cache_mode memory_resident(缓存模式)。
这将导致尽可能多的这个文件的块被无限期地保留在缓存中。实际的数字是缓存大小和内存驻留百分比的一个因素,在set_tuning_parameters命令中设置。
下面的序列显示了一个程序化使用的例子(使用test_system_calls进行说明)。
tsc: s$attach_port p scratch
tsc: s$open p -io_type update
现在,提供一个512GB左右的地址空间。
tsc: extend_stream_file p 549235720192 (s$control EXTEND_STREAM_FILE)
并用它来存储数据。
tsc: s$seq_position_x p bwd_by_bytes 3 (扩展后的当前位置为EOF)
tsc: s$write_raw p END
tsc: s$seq_position_x p bof
tsc: s$write_raw p START
tsc: s$seq_position_x p fwd_by_bytes 2000。
tsc:s$write_raw p 2000
注意:s$seq_position也支持定位到绝对字节偏移量的操作码。
结果是这样的,文件在磁盘上只占用了两个数据块。
.dump_file scratch -brief
%swsle#Raid4>otto>d-3>new>scratch 15-02-25 16:04:17 est
块号1
000 53544152 54000000 00000000 00000000 |START...........|
010 00000000 00000000 00000000 00000000 |…………….|
=
7D0 00000000 00323030 30000000 00000000 |…..2000…….|
7E0 00000000 00000000 00000000 00000000 |…………….|
=
FF0 00000000 00000000 00000000 00000000 |................。
座号131870736
000 00000000 00000000 00000000 00000000 |…………….|
=
FF0 00000000 00000000 00000000 00454E44 |.............END|。
注意:块1和131870736在缓存中,通常不会被写入磁盘,尽管磁盘空间是为它们预留的,如果缓存资源紧张的话,需要将它们写入磁盘。上面的dump_file命令看到的是缓存中的块,而不是读磁盘。
当一个RAM文件被停用(不再在任何进程中打开)时,VOS会截断文件(避免将修改后的块写入磁盘)并释放所有磁盘空间。在典型的情况下,上述序列除了写入两个文件映射块外,根本没有任何磁盘I/O,而这两个文件映射块最终会被丢弃。
TSC: S$close p
现在文件是空的,不占磁盘空间。
tsc: ...dump_file scratch
%swsle#Raid4>otto>d-3>new>scratch 15-02-25 16:07:12 est