我问是因为字符串比较很慢,但索引很快,而且我写的很多脚本都是用 bash 编写的,据我所知,它会为每个可执行文件调用执行完整的字符串查找。如果不对每个步骤执行字符串查找,所有这些ls
' 和grep
' 会快一点。当然,这现在深入研究了编译器优化。
无论如何,有没有一种方法可以在 Linux 中仅使用其 inode 编号直接调用程序(假设您只需要为所有调用查找一次)?
我问是因为字符串比较很慢,但索引很快,而且我写的很多脚本都是用 bash 编写的,据我所知,它会为每个可执行文件调用执行完整的字符串查找。如果不对每个步骤执行字符串查找,所有这些ls
' 和grep
' 会快一点。当然,这现在深入研究了编译器优化。
无论如何,有没有一种方法可以在 Linux 中仅使用其 inode 编号直接调用程序(假设您只需要为所有调用查找一次)?
最简洁的答案是不。
更长的答案是 linux 用户 API 不支持通过任何使用索引节点号的方法访问文件。对 inode 编号的唯一访问通常是通过公开 inode 编号的 stat() 系统调用,这对于识别两个文件名是否是同一文件很有用,但不用于任何其他用途。
通过 inode 访问文件将违反安全性,因为它会绕过包含链接到 inode 的文件的目录的权限。
最接近的方法是通过打开的文件句柄访问文件。但是你也不能从那里运行程序,这仍然需要通过路径打开文件。(如评论中所述,出于安全原因,此功能已与其他 *at 系统调用一起添加到 linux,但不可移植。)
还有很多方法可以使用 inode 号来查找文件(基本上,爬行文件系统并使用 stat)然后正常运行它,但这与您想要的相反,因为它比仅访问文件要昂贵得多按路径名,也不会删除该成本。
话虽如此,担心这种类型的优化可能没有实际意义,因为 Linux 已经对内部 inode 查找进行了大量优化。此外,传统上,shell 会散列可执行文件的路径位置,因此它们不必
$PATH
每次都从所有目录中寻找它们。是的,可以通过 inode 执行文件:
但是,性能激发了这个问题,而以上并不是性能。不仅是遍历目录结构来查找具有该 inode 的文件(并且可能有多个),而且在引擎盖下,inode 编号被解析为路径,并将该路径交给内核执行。但为什么?
内核公开了 exec 函数族(
execl
,execvp
等),它们都包装了内核函数execve
。该函数用一个新的过程映像替换当前的过程映像,该过程映像是通过从给定文件路径读取内容来引导的。因此,内核提供的执行程序的每一种方式都需要通过路径给出。通过使用文件路径作为入口点,我们可以获得与文件路径相关的所有访问控制优势,因此,“按路径”API 是 Linux 中唯一用于执行程序的 API。然而,存在一种繁琐且不能保证在所有环境中工作的机制,允许您从内存中调用程序。由于内存中的任何东西都必然比磁盘上的任何东西快,这就驱动了问题的核心:如何尽可能快地运行程序。
2002 年初,一位(著名的)黑客 grugq 引入了 userland exec 的概念。这不是 shell 的
exec
函数:它是内核函数执行的每一步的模拟execve
,只是在用户空间中编写。这对于想要隐藏其活动的黑客来说是理想的选择,因为它允许在 .net 通常的访问控制机制之外执行程序execve
。这个方法的实现需要大量的助手来清理地址空间、加载动态链接器(如果需要)、初始化堆栈等等。该机制还需要将所需代码加载到某些类型的内存中。
也有适当的反措施来使这种事情变得困难,但请注意,并非不可能。所需要的只是目标系统具有页面对齐的内存、将内存标记为可执行的能力以及跳转到内存中任意点的能力。这些要求通常转化为:您必须用 C 编写它并在没有 SELinux 或没有完全启用 SELinux 的系统上使用它。我不会在这里详细介绍实现细节,但会提供允许您自行探索的链接。
因此,如果您的 Linux 系统满足上述要求,那么您可以通过以下方式从内存中执行代码:
find / -inum 242 -exec cat {} \;
内核、文件系统和 shell 都经过调整,使程序的查找和执行在工作所需的总开销中所占的比例可以忽略不计。在内存中加载一个程序并从那里执行它并不真正属于一般用例的领域,所以除非为了好玩而这样做,否则我会说你想要在投入时间尝试之前对性能进行基准测试。
参考:
这不是对 i-nodes 问题的直接回答,而是一种避免在 shell 脚本中查找标准实用程序路径的可能方法。
BusyBox是一个将许多标准 Unix 实用程序组合到一个可执行文件中的程序,该可执行文件的大小远小于它所替代的所有工具的总和。它在嵌入式领域非常流行,其中磁盘大小通常很重要。在典型的基于 BusyBox 的系统中,
sh
,ls
和grep
都是指向 的符号链接busybox
。因此,调用ls
并且grep
只会busybox
调用自身两次的 shell 脚本。BusyBox 有一个实验性的特性,叫做“standalone shell”。启用后,充当 shell 的 BusyBox 不会为其实现的实用程序执行路径查找。相反,它只是通过
/proc/self/exe
使用正确的参数来执行自己。例如,如果它运行一个调用 的 shell 脚本,它会执行,而不是在grep
中查找。内核中仍然存在路径查找,但无论调用的实用程序如何,它总是相同的,并且可执行映像已经在内存中,因此无需加载它。grep
$PATH
/proc/self/exe grep <arguments>
/proc/self/exe
但是请注意,BusyBox针对大小而非速度进行了大量优化,因此如果您关心节省几微秒,它可能不是您的最佳选择。此外,如前所述,“独立 shell”功能被标记为实验性的。
不,不是,原因很简单:您在问题中使用单数形式“一个程序”和“它的inode 编号”,但 inode 不是唯一的:系统中可以有多个具有相同 inode 的文件数字。
因此,根据简单的常识,您可以做的最好的事情是“仅使用其 inode 编号直接调用一组程序中的一个或多个”,但是如果没有有关该程序的附加标识信息,您不能调用特定程序以便挑选出一组程序中的一个程序。
当然,这样的识别信息之一可能是它的路径……在这一点上你回到了第一点。