跳转至主要内容

如果你曾经尝试过使用基于POSIX的程序来处理VOS结构化文件,你可能会遇到一些限制或者看到一些你不理解的行为。在这篇文章中,我将试着解释一下是怎么回事。

VOS支持4种类型的文件:顺序式、相对式、固定式和流式。前3种格式被称为"结构化"文件,因为文件系统会跟踪记录的边界。可用的I/O操作可以读取和写入整个记录。最后一种格式被称为"非结构化"文件,因为记录边界是隐含的;换行字符限定了记录的界限。可用的I/O操作是读取和写入字节序列。

一个POSIX兼容的环境,如在Unix®或Linux©系统上,只有一种本地文件类型,被称为"常规文件"。VOS流文件组织相当于POSIX常规文件。

VOS POSIX运行环境将这4种类型的文件都归为POSIX常规文件。所以至少在理论上,任何POSIX程序都可以读写这4种文件类型中的任何一种。然而,事实并非如此简单。

由于POSIX API以字节序列来定义所有的I/O操作,而VOS以记录序列来定义I/O操作(在结构化文件上),因此VOS POSIX运行时通过在用户空间中缓冲当前记录,在缓冲区上执行POSIX I/O操作,然后在适当的点上将缓冲后的记录写回。

如果POSIX程序知道每条记录的大小(比如对于一个固定的文件),如果它读写的字节数是准确的,那么缓冲区的存在并不影响操作,这两种类型的I/O操作的映射很容易理解,也很有效率。

但如果POSIX程序只是读或写字节流,而不考虑底层记录的大小,那么POSIX语义与VOS语义的映射虽然定义得很好,但一般来说并不是很有用,而且往往效率很低。某些操作,比如寻找到一个字节位置,或者重写一个延伸到记录边界的字节序列,充其量是低效的,最坏的情况下是不可能的。

还有就是换行字符的处理问题。

POSIX常规文件和VOS流文件都使用换行符来区分记录边界。然而,结构化文件中的VOS记录通常不包含任何换行符。例如,当一个VOS编辑器(如edit、emacs或line_edit)创建一个新的顺序文件时,每个记录都包含一行文本。但是记录并不是以换行符结束的。按照惯例,这些程序都假定一个包含文本的顺序文件在每条记录的末尾都有一个隐含的换行符。对于相对文件和固定文件也是如此。但这里有一点很重要:任何文件(VOS、Unix、结构化或非结构化)的属性都不会记录文件是包含文本还是二进制数据。区别是留给访问文件的程序的。

这种情况给VOS POSIX运行时带来了一些难题。它需要知道一个VOS结构化文件是否包含文本或数据,以便知道是否要给每条记录加上一个新行。如果文件包含文本,它应该附加一个新行。如果文件中包含数据,则不应该添加换行符。

答案是VOS POSIX运行时依赖于调用者提供这些信息。默认情况下,POSIX运行时将结构化文件视为包含文本,并附加一个新行;调用者可以通过提供O_TEXT打开模式来明确要求这种行为。调用者如果想把一个VOS结构化文件当作包含数据的文件,必须提供O_BINARY打开模式。这两种模式是相互排斥的;如果指定了其中一种,就不能再指定另一种。这些模式对于流文件来说是不需要的,所以在这种情况下会被忽略。

对于正在阅读这篇文章的语言律师来说,让我迅速指出,O_TEXT和O_BINARY都是POSIX标准的扩展;它们不是由POSIX本身定义的。它们通常只存在于区分文本和二进制文件的操作系统上(如VOS),或者有一个特殊的行尾约定(如Windows;使用CR-LF)。

根据策略,当Stratus 将基于 POSIX 的软件移植到 OpenVOS 时,我们会对其进行修改,以排除 FIXED 和 RELATIVE 文件的使用,并将 SEQUENTIAL 文件限制为只读访问。我们还假设所有的顺序文件都包含文本。根据我们的经验,这些规则使得使用STREAM或SEQUENTIAL文件作为POSIX程序的输入变得实用,同时避免了在SEQUENTIAL输出文件上进行面向字节的操作的固有的低效率。

综上所述,最好的方法是坚持在基于POSIX的程序中只使用STREAM文件(用于输入或输出)和SEQUENTIAL文件(只用于文本的输入)。如果你有结构化文件中的二进制数据,写一个小程序把它复制到流文件中,然后用POSIX程序使用流版本的文件。如果在FIXED或RELATIVE文件中有文本数据,希望用POSIX程序处理,请先将文件复制到STREAM文件中。

© 2024Stratus Technologies.