为什么“ls”需要一个单独的进程来执行?

cri*_*ron 14 ls cd-command fork

为什么ls需要一个单独的进程来执行?我知道为什么像这样的命令cd不能通过分叉机制执行,但是如果ls不分叉就执行有什么危害吗?

Chr*_*own 18

答案或多或少ls是外部可执行文件。您可以通过运行查看它的位置type -p ls

那么为什么不ls内置到外壳中呢?嗯,为什么会这样?shell 的工作不是包含所有可用的命令,而是提供一个能够运行它们的环境。一些现代 shell 具有echo, printf, 和它们的同类作为内置函数,它们在技术上不必是内置函数,但是当它们重复运行时(主要是在紧密循环中)出于性能原因而这样做。如果不将它们内置,shell 将不得不为每次调用它们分叉并执行一个新进程,这可能会非常慢。

至少,运行ls外部可执行文件需要运行 exec 系列系统调用之一。您可以在不分叉的情况下执行此操作,但它会替换您正在使用的主 shell。您可以通过执行以下操作来查看该实例中发生的情况:

exec ls; echo "this never gets printed"
Run Code Online (Sandbox Code Playgroud)

由于您的 shell 的进程映像已被替换,执行此操作后将无法再访问当前的 shell。为了使 shell 在运行 ls 后能够继续运行,必须将命令内置到 shell 中。

Forking 允许替换不是您的主 shell 的进程,这意味着您可以在之后继续运行您的 shell。


Jon*_*ham 15

猛砸参考手册状态:

内置命令是实现单独实用程序不可能或不方便获得的功能所必需的。

也就是说,shell 被设计为包含内置命令,如果:

  1. POSIX 标准要求
  2. 需要访问 shell 本身的命令,例如作业控制内置命令
  3. 非常简单的命令,不依赖于操作系统,并在作为内置程序实现时提高执行效率,例如 printf

ls命令不符合上述任何要求。

但是,这里没有阻止ls作为内置程序实现的编程约束 ,它与 bash 解释器在同一进程中执行。命令没有被实现为 shell 内置命令的设计原因是:

  1. shell 应该与文件系统分开 - 没有内置命令应该依赖于任何文件系统或外围设备的正确操作
  2. 可能是文件系统类型或操作系统相关的命令应该是一个单独的可执行文件
  3. 您可能想要通过管道传入或传出的命令应该是一个单独的进程
  4. 您可能希望在后台运行的命令应该是一个单独的可执行文件
  5. 具有大量可能参数的命令最好在单独的可执行文件中实现
  6. 应该具有相同输出的命令,无论哪种类型的 shell(bash、csh、tsh 等)调用它们都应该是独立的可执行文件

关于第一个原因 - 您希望外壳尽可能独立且具有弹性。您不希望 shell 卡在ls“未响应仍在尝试”的 NFS 安装上。

关于第二个原因 - 在许多情况下,您可能希望将 shell 用于使用 Busybox 或其他具有不同ls实现的文件系统的系统。或者甚至在具有不同ls实现的操作系统中使用相同的 shell 源。

关于第三个原因 - 对于诸如find . -type d | xargs ls -lad很难或不可能ls在与 shell 解释器相同的进程中实现的表达式。

关于第四个原因 - 某些ls命令可能需要很长时间才能完成。在此期间,您可能希望 shell 继续执行其他操作。


注意:请参阅本有用的职位沃伦·扬响应类似的问题。