我正在运行一个在 bash 中调用的简单可执行文件hello
。它询问用户输入并打印出响应。我像这样运行它./hello
。
提示和用户输入其响应都发生在当前 shell 中,但我认为它应该在不同的 shell 中运行。我之所以这么认为是因为您可以使用 source 在当前 shell 中运行 exe。
谁能向我解释一下这是如何运作的?
在尝试研究这个问题时,我经常遇到术语“shell 环境”和“shell 上下文”。它们是一样的吗?
答案1
你可能会说“shell环境”是指当前shell的环境,其中包括当前的环境变量。该环境由任何启动的子进程(子 shell 或其他)继承。
“shell 上下文”是一个不常用的术语,但我假设它相当于“进程上下文”。对于 shell 脚本,这将包括 shell 环境以及当前的 shell 变量、文件描述符(标准输入、标准输出和标准错误以及任何其他显式打开的)、信号处理程序(使用trap
)等。如果这是一个 C 程序,进程上下文将在对 的调用中继承fork()
,但不能在后续exec()
调用中继承(只有环境在对 的调用中幸存exec()
)。
当您运行hello
程序时(我假设它是一个 shell 脚本),输入和输出发生在执行该hello
脚本的 shell 的上下文中。这是“当前外壳”。您输入的 shell./hello
是其父 shell,并hello
继承其环境。
在内部,父 shell 执行fork()
并exec()
调用来启动最终将运行脚本的 shell hello
。
事实上,hello
脚本在同一位置进行提示终端因为您启动脚本的位置仅意味着运行脚本的 shell 是当前的前台进程。父 shell 正在等待它完成。完成后,父 shell 将再次成为终端中的前台进程。
source ./hello
当您使用或启动脚本时. ./hello
,脚本将在与您键入该命令的 shell 相同的上下文中执行。这意味着它可能会修改交互式 shell 的上下文和环境。例如,它可能会更改当前工作目录(更改环境)或安装信号处理程序(更改上下文),并且当脚本完成执行时这些更改仍将是“活动的”。
如果hello
程序是编译的二进制文件,它将继承调用 shell 的环境,但不会共享其上下文(文件描述符等)。它并不是真正在子 shell 中运行,因为它不是 shell 脚本。父 shell 将移至后台,等待程序完成,就像 shell 脚本一样。从父 shell 的角度来看,启动已编译的二进制文件或 shell 脚本没有区别。
已编译的二进制文件不能以source
或.
(点)开头,因为 shell 不知道如何解释二进制文件。
这个答案有点挥手,但我相信它基本上是正确的。如果有任何内容需要更正或添加,请发表评论(或编辑)。