命令行应用程序通常在用户命令之间关闭吗?

命令行应用程序通常在用户命令之间关闭吗?

我最近偶然发现了一些显然纯粹通过命令行运行的应用程序。Git 就是其中之一。

当我在 cmd.exe、bash 或 powershell 中运行它时,我通常首先指定通向 git.exe 的路径,然后输入命令。然后 Git 会执行一些操作,下次我必须再次执行相同的操作。

我一直认为,发生的情况是,每次调用 git.exe 命令时,它都会通过函数参数检索用户命令main(int argv, *char[] argc)并终止,这意味着在每个用户命令之间它实际上都会关闭。

但这是真的吗?而且通常都是这样吗?

答案1

通常情况下是的。每次运行新命令时从 shell 中是一个生成或 fork/exec 的全新进程(除了内置于 shell 的进程),并且每当您返回到 shell 的提示符时,都意味着前一个进程已退出1。 (实际上,一旦 shell 分叉,其主进程通常不执行其他任何操作,只是调用 waitpid() 并专门等待子进程退出,然后再将新提示打印到 stdout。)

操作系统不提供这些调用之间的任何内置连续性;每个新的 git.exe 都从 main() 重新开始,并且必须.git再次从文件夹中读取存储库的状态。

不过,相反的情况也适用:如果一个命令没有返回到 shell 的提示符,而是显示它自己的提示符(比如 python.exe 显示>>>或 diskpart.exe 显示DISKPART>),则表示它仍在运行——您在 输入的所有内容都>>>将被同一个 python.exe 实例读取,直到您最终退出回 shell。

查找方法之一是查看进程列表 -tasklist或者任务管理器的“详细信息”将显示基本信息,但 Process Hacker 和 Sysinternals ProcExp 都提供了当前正在运行的所有进程的更清晰的树状视图。(同时,Windows 上的 Sysinternals ProcMon - 或 Linux 上的 forkstat - 可以显示进程启动/退出事件。)


1还要注意的是,这只与 shell 生成的初始进程有关——并不一定意味着它的孩子们已退出。(例如,Git 操作有时会启动“git gc”进程进行后台维护。)

一个特别相关的例子是 Git 可能会在 Windows 上自动启动的“git fsmonitor”进程,它充当文件系统元数据的持久内存缓存——因此根据设计,它应该在第一个命令之后继续运行,并允许进一步的 Git 命令连接以某种方式(例如通过本地套接字)

Linux 上的另一个类似示例是 GnuPG(“gpg”命令),它将在第一次运行时启动“gpg-agent”进程,并且下一次“gpg”调用可能会在需要代理的服务时连接到 gpg-agent 的现有实例。

因此,尽管你的 shell 不会“重新连接”到应用程序,而是每次都会生成一个新的 git.exe 进程,应用程序本身可能使用某种形式的 IPC 连接到先前启动的后台服务。

答案2

您混淆了两种类型的控制台命令。
有些命令运行操作并完成,而其他命令则打开自己的控制台。在 dos 世界中,控制台示例是 diskpart。它有自己的控制台命令来管理磁盘上的分区,并以 exit 命令结束。

对于控制台命令的行为,没有一个硬性规定。这取决于新控制台的复杂性,以及您是否想确保用户在会话期间不使用 DOS 命令,或者您的控制台命令是否与 DOS 命令相同但具有完全不同的选项。

答案3

不清楚您所说的‘它关闭’是什么意思。

如果您有一个简单的程序(例如著名的“Hello, world”),当您运行它时,您所在的 shell 通常会 fork 并执行该程序。在程序结束时,它就会结束。对于许多实用程序(例如lsnetstat等等)来说都是如此。

程序也可以等待 STDIN。如果您不提供文件名,、grepsed许多cat其他程序将等待 STDIN。当 STDIN 到达文件末尾(UNIX/Linux 中为 ^D,MS-dos 等中为 ^Z)时,程序将结束其处理并以与简单实用程序相同的方式结束。

在 MS-Dos 下,您可以将程序保存在内存中,对特定事件作出反应。您可以将一些中断向量连接到它,而不是让程序直接结束,而是调用终止驻留程序。最著名的是 Sidekick 编辑器。

在 Unix/Linux 下,一个程序可以 fork 另一个程序。因此,一个程序可以 fork 某个无限循环,并在 fork 的另一部分无限循环继续运行时终止。这就是(非常简单地描述)许多守护进程所做的。

我希望 Windows 具有一些与守护进程类似的构造,但我实际上没有资格对此发表评论。

相关内容