【发布时间】:2017-03-16 05:03:12
【问题描述】:
让我解释清楚。
以下是我的要求:
- 假设有一个命令具有指定为“-f”的选项,该选项将文件名作为参数。
- 现在我有 5 个文件,我想创建一个合并这 5 个文件的新文件,并将新文件名作为上述命令的参数。
-
但是有区别
- 读取单个文件并
- 合并所有文件并读取合并文件。
在第二种情况下生成的 IO(从 5 个文件读取 + 写入合并文件 + 我们的命令对给定文件执行的任何 IO)比 IO(我们的命令对给定文件执行的任何 IO)多在第一种情况下生成。
我们可以减少这种不需要的 IO 吗?
最后,我真的根本不想要合并的文件。我创建这个合并文件只是为了让命令读取合并文件的内容。
也就是说,我也不想要这个实现。文件大小不是那么大,可以有额外的可忽略不计的 IO。但是,我只是想知道这是否可以做到。
所以为了实现这一点,我有以下理解/问题:
- 通常所有命令(采用文件名参数)的作用是读取文件。
- 在我们的例子中,文件名(文件路径)还没有准备好,它只是一个存在的虚拟/虚构文件名(作为所有文件的合并)。
- 那么,我们可以创建这样的虚拟文件名吗?
- 什么是文件名?它是存储位置的间接 inode 条目。
- 在我们的示例中,各个文件具有不同的 inode 条目,并且所有 inode 条目具有不同的存储位置。而且我们的虚拟/虚构文件实际上没有inode,即使我们可以创建一个虚构的inode,它也只能指向内存中的存储(因为没有从一个文件的存储位置引用另一个文件的存储位置在磁盘中)
- 但是,假设使用高级编程,我们能够使用虚构的 inode 创建一个虚构的文件路径,它指向内存中的存储。
- 现在,当我们将那个假想的文件名作为参数并且当命令试图打开那个假想的文件时,它发现它的 inode 条目是指内存中的存储。但实际内容存在于磁盘中而不是内存中。所以,数据还没有加载到内存中,除非我们明确地读取它。因此,我们再次需要先读取数据。
简单的说,由于磁盘存储中没有连续性或对下一个文件数据的引用,因此需要先将合并后的数据加载到内存中。 p>
所以,根据我的推论,似乎我们至少需要将数据放入内存中。但是,由于命令本身需要读取文件(如果不是整个文件,至少是其中的一部分,直到命令的操作完成 - 让它解析或其他)。因此,使用这种方法,我们可以节省一些重要的 IO,如果它真的是一个大文件。
那么,我们如何创建那个虚拟文件呢?
- 我的第一个答案是将合并的文件写入 tmpfs 并引用该文件。但它是唯一的选择还是我们实际上可以指向内存中的存储位置,而不是 tmpfs? tmpfs 不是选项,因为我的脚本可以从任何服务器运行,我们需要有一个适用于所有服务器的解决方案。如果我在脚本中提到在 /dev/shm 创建合并文件,它可能会在没有 /dev/shm 的服务器中失败。所以我应该能够直接加载到内存中。但是我认为普通用户将无法访问内存,因此,没有 shm 似乎无法完成。
请让我知道您的 cmets,如果我的理解有任何错误,请纠正我。即使对我的水平来说很复杂,也请发布您的答案。至少,几个月后我可能会明白。
【问题讨论】:
-
通过一些杂耍,您可以使进程从命名管道中读取(并让 producer 写入该管道)
What is a filename?这是一个包含 指向一个inode的指针。 (编号) -
嗨,实际上我只能提供文件名参数,我不能破解它,因为它是一个二进制文件
-
因为:(1) 您不能更改命令 [binary blob]。 (2) 不关心输出文件 (3) 不能阻止命令写入输出 (4) 只希望命令读取输入文件。试试:
cmd -f /dev/null f1 f2 f3 f4 f5。这几乎是最快的。有什么理由不起作用? -
@CraigEstey 我不明白你为什么提到 /dev/null。但是,我尝试了它没有用。该命令只接受一个文件作为参数。现在,我创建了一个条件来检查 /dev/shm 并在那里创建组合文件(如果存在),否则在 /tmp/ 中创建。我很好奇是否有人可以用编程方法回答这个问题。
-
我的命名管道解决方案非常真实(而且它确实有效!)。但我怕你不明白。 (顺便说一句 二进制文件 :您的意思是可执行文件,或者其名称应该作为参数提供给可执行文件的实际数据文件?)
标签: c linux memory memory-management kernel