不区分大小写的文件系统如何访问文件?

不区分大小写的文件系统如何访问文件?

我工作单位的一名程序员一生都在使用 Linux,他正在斥责 Windows 的文件系统不区分大小写(还有其他问题),他说这是最糟糕的想法,永远不会有好处。我说那只是因为他习惯了区分大小写的文件系统,而使用不区分大小写的文件系统更有意义(我的理由部分是,我的名字是David,但如果你提到我,david我仍然知道你指的是我,文件也应该如此)。然后他解释了他的立场,指出不区分大小写的文件系统必须导致性能下降。

所以现在我想知道...如何不区分大小写的文件系统如何访问文件?让我试着解释一下我的想法:

假设你有一个区分大小写的文件系统(和 OS 内核等)这样实际上,如果存在一个名为 的目录exampleDir,我必须准确输入cd exampleDircd 进入该目录。如果我输入cd exampledir,我应该收到目录不存在的错误。在我看来,这似乎是一个简单的案例。当我输入命令时,文件系统可以简单地获取我输入的准确字符(忽略内核可能会将当前工作目录路径添加到字符串等)并开始浏览可用文件名列表,对每个名称进行直接比较;例如:

for(var i = 0; i < files.length; i++) {
    if(filename == files[i]) return true;
}

现在有趣的部分是,不区分大小写的文件系统(假设情况-保存,按照 Windows 的规定)。实际上,如果存在一个名为 的目录exampleDir,我可以输入cd exampleDircd eXamPleDIr,我仍然可以成功进入该文件夹。我真正想知道的是,实现这一点的代码是什么样的。为了保留大小写,目录名必须与其大小写一起存储。那么这是否意味着你必须这样做每次想要通过文件名访问文件时,都需要将文件名转换为小写或大写吗?这会对性能造成多大的影响?是否有任何技巧可以减少使用不区分大小写的文件系统带来的性能下降?我想象中的文件系统代码应该是这样的:

for(var i = 0; i < files.length; i++) {
    if(toLowercase(filename) == toLowercase(files[i])) return true;
}

请注意:因为我的问题似乎没有明确说明这一点,所以我绝对不是我并不问哪种类型更好,也不问优点和缺点是什么。我仅有的询问不区分大小写的文件系统(从技术角度来说)如何应对人类可以随机输入大小写的文件名这一事实。

答案1

操作系统通常使用句柄。调用“打开”函数,指定文件名,并返回句柄。进一步的 I/O 调用采用句柄,而不是文件名。

其他需要文件名的功能包括创建文件、列出目录和删除文件。

因此,处理不区分大小写造成的任何性能损失实际上都不会影响实际的 I/O,只会影响文件管理。

有些程序使用锁定文件来指示资源正在使用中。这可能会导致大量的创建和删除。

但是,进行两次比较而不是一次比较的开销可能只是一些额外的汇编语言指令。这意味着少于 50 个左右的周期。如果缓存未命中,则可能是 500 或 5000 个周期。

这真的不值得担心,除非你真的担心在短时间内创建/删除数十亿个文件的性能。高磁盘 I/O 应用程序包括数据库之类的东西,数据库通常会打开一些非常大的文件并在使用数据库时保持它们打开。因此,这些类型的应用程序(通常需要所有磁盘 I/O)不会进行大量需要解析文件名的调用。

在处理文件名的时间尚未到达瓶颈之前,介质的速度就已经成为瓶颈。

答案2

如果你假设文件系统本身区分大小写,因为它允许您不受限制地使用大写和小写字符存储文件名,那么对于某些操作,必然存在某种性能损失。

例如,假设您有一个文件foobar.txt,然后您告诉程序将其保存为,fooBar.txt而不检查它是否已经存在。

对于您在不区分大小写的系统上创建的每个文件,它只需执行一次搜索 - 您指定的确切文件名。保存,完成。

对于在区分大小写的系统上创建的每个文件,它必须搜索“foobar”“Foobar”“fOobar”的每个组合,或者必须缓冲文件列表,然后转换全部的将文件名列表转换为小写或大写,然后搜索是否存在重复文件。读取文件时也是如此,如果完全匹配不起作用,则必须检查所有可能性。

文件系统驱动程序检查文件是否存在所需的工作量存在巨大差异。

对于读取文件名,对系统的惩罚要小得多,在几乎所有情况下,文件系统驱动程序都会将文件列表传递给请求它的程序。我确信我曾看到有人提到,你可以在 NTFS 文件系统上使用不区分大小写的系统(如 Linux)创建“重复”文件名,而 Windows 只会处理它。

不区分大小写系统确实需要程序员多做一些工作,但它从用户的角度稍微简化了事物的视图。两种做事方式各有利弊。

首先,我发现在区分大小写的系统中,读取文件时会出现与大小写相关的编程错误。如果您的程序对请求进行了硬编码/etc/fish,而有人将其重命名为/etc/Fish(或者您忘记按住 shift 键来输入“f”),那么您将收到一个错误,而这在区分大小写的系统中是不会发生的。

这完全取决于您在哪里付出努力,并且两种做事方式都有利弊。

相关内容