无论任何外壳如何,进程都可以运行吗?

Yoa*_*ein 8 linux bash environment-variables process

我试图从操作系统进程的角度来理解 shell 和终端的概念以及它们之间的确切关系。所以我在这个领域几乎没有问题。

  1. 健全性检查:据我所知,shell 是用户可以与操作系统交互的界面,即:运行其他进程。虽然shell(例如Bash)只是另一个进程。那正确吗?

  2. 有没有办法运行一个不会是 shell 进程的子进程的进程?

  3. 环境变量:在bash,还有,当你生成一个shell中运行多个脚本,例如.bashrc.bash_profile等(取决于外壳类型-互动与非互动,登录与非登录)。这些脚本定义了环境变量。如果有一种方法可以不管任何 shell 来运行进程,那么环境变量从何而来?

use*_*686 15

健全性检查:据我所知,shell 是用户可以与操作系统交互的界面,即:运行其他进程。

是的,但是“外壳”专门是一个用户界面,而不是一个编程界面。其他程序不需要与之交互——它们可以直接使用相同的系统调用来创建新进程。

因此命令行外壳与其他程序处于同一级别,例如服务管理器或图形用户界面(图形外壳)。

虽然shell(例如Bash)只是另一个进程。

是的。在类 Unix 系统上,它是一个完全正常的、无特权的进程。

有没有办法运行一个不会是 shell 进程的子进程的进程?

从用户的角度来看:是的,有几种方法。

  • 大多数 shell 都有一个exec关键字,它会导致新程序替换shell(保留相同的 PID 和父级),这可能不是您的意思,但从技术上讲是您所要求的。

  • 图形桌面会话通常会在不调用 bash 或任何其他 shell 的情况下启动,这自动适用于通过图形菜单启动的应用程序。应用程序的父进程将是负责显示菜单的任何进程(例如窗口管理器或面板)。

  • 当前流行的systemd init 系统在启动服务时根本不使用 shell,因此您可以定义一个 .service 并启动它——服务的父级将是 init 本身。它还具有允许使用 即时创建临时服务的功能systemd-run,并具有相同的结果。

从程序员的角度来看,只需使用fork()execve()系统调用来启动一个新进程。(有特定于操作系统的细节,例如 fork() 实际上可能是不同调用的包装器,但它仍然以相同的方式工作。)

事实上,即使程序想要调用一个 shell,它也会通过创建一个新的子进程并使用相同的 fork+exec 运行 /bin/sh 来实现。没有特殊的系统调用来运行 shell。(程序员可以在用 C 编写时使用例如 system() 或在 Python 中使用 os.system() ,但这些仍然只是围绕 fork/exec 的便利包装器。)

环境变量:在 bash 中,有几个脚本会在您生成 shell 时运行,例如 .bashrc、.bash_profile 等(取决于 shell 的类型 - 交互式与非交互式、登录与非登录)。这些脚本定义了环境变量。如果有一种方法可以不管任何 shell 来运行进程,那么环境变量从何而来?

好吧,有时他们不会。(当试图让图形应用程序选择环境自定义时,这是一个真正的实际问题,这取决于特定图形环境的启动方式。)

不过,总的来说,环境变量并不是CLI shell 所独有的。每个进程,无论它是如何启动的(甚至包括 init 进程),都会接收一个包含其命令行的字符串数组——以及一个包含其环境变量的字符串数组。启动子进程时,它可以指定不同的环境或允许继承其自身环境的副本。

因此,当您登录时,您的 shell 已经从其父级接收了一些初始环境变量。这些启动脚本(bashrc 等)只是一个方便用户自定义环境变量的地方,shell 的子进程将继承这些环境变量。


这个答案的许多部分也完全适用于 Windows——尽管它的图形界面有点复杂,但 CLI shell(cmd.exe 和 PowerShell)仍然是在正常操作中根本不使用的普通程序。唯一的主要区别是 Windows 有一个“CreateProcess”调用,而不是 Unix 风格的单独“fork + exec”调用。