shell 是否具有与其他命令相同的标准输入、标准输出、标准错误?

shell 是否具有与其他命令相同的标准输入、标准输出、标准错误?

例如,bash位于/bin/bash下,这意味着它是一个命令,每个命令都有三个(0,1,2)孔:标准输入,标准输出,标准错误。

这对于 shell 来说也是 100% 正确吗?还是因为 shell 作为命令或进程的特殊含义而有什么不同?

答案1

它与任何其他程序相同。这允许您像其他程序一样重定向和管道 I/O。

echo "cat filename" | bash

当从管道读取其标准输入时将执行该cat filename命令。bash

bash -c "echo foo" > filename

将执行该echo foo命令,并将输出重定向到该文件。

在 Unix 上,shell 没有什么“特别”的地方。它只是一个普通的程序,其主要目的是执行其他程序。

答案2

让我们区分一些术语:

A命令是你在 shell 中输入的内容。它可能是一个别名或一个外壳函数,或者它可能指的是可执行文件

一个可执行文件可能是一个二进制可执行文件(即直接包含机器代码的代码)或脚本。脚本包括bash脚本、sh脚本、perl脚本、awk脚本、sed脚本、python脚本等。等人。

脚本的前两个字节(如果要直接作为可执行文件执行)必须是#!,这是一个“幻数”,向内核发出信号以读取更多字节,直到读取换行符,将这些字节解释为到一个的路径二进制可执行文件,可能有一个由空格分隔的参数(例如#!/bin/awk -f),然后执行二进制可执行文件,脚本本身的路径作为参数传入。

最终,内核唯一可以真正执行的是机器代码,即二进制可执行文件。二进制可执行文件,例如 sh、bash、perl、python、awk 等。等人。叫做口译员。 他们解释脚本并执行其指令。但它们必须存在于机器代码本身中才能被执行。

当程序(二进制可执行文件)实际由内核运行时,它作为过程。 二进制可执行文件只是一个包含指令的文件。 A过程是“程序的运行实例”;更具体地说,它是内置于内核中的一个抽象,具有关联的内存、环境变量、进程 ID (PID)、文件描述符它可用于输入和输出以及其他属性。您可以“同时”多次运行一个可执行文件(实际上并不是在单核机器上同时运行,而是由于内核分配 CPU 周期的方式,它会似乎同时)并且每个正在运行的实例将是不同的进程,即使它们都是同一程序的实例。

0、1 和 2(标准输入、标准输出和标准错误)是文件描述符。 说实话,它们的存在只是按照惯例。您可以使用 C 创建一个程序,该程序将启动(运行)其他程序(执行各种二进制可执行文件),而无需向它们提供这些文件描述符。 然而,由于标准程序都是在假设文件描述符 0、1 和 2 可用的情况下编写的,因此您可能只会得到错误(在大多数情况下),并且程序将无法正常工作。

要真正完全理解这一点,您应该理解一个过程是如何产生的。 这有点像诞生的奇迹。 ;) 所有进程都必须由其他过程。不用担心启动系统时第一个进程如何启动,PID 为 1 的进程称为“init”,它会启动操作系统运行所需的其他基本进程。

一个进程如何启动另一个进程有两个基本步骤:执行。 这两个都是系统调用,也就是说它们是进程发送的操作/请求到内核只有内核才能真正实现。

“Fork”的意思是(简而言之)“内核,请给我复制一份”。 (“Me”是一个正在运行的进程。)内核制作进程的完整副本——它的文件描述符、内存、执行状态(它在遵循组成它是实例的程序的指令时所处的位置),环境变量等等。所以它是该过程的“克隆”。现在你如何区分原件和副本呢?仅通过一件事:系统调用的返回状态fork。子进程获取“0”(成功),父进程获取新创建的子进程的PID。因此,通过检查此返回状态,每个进程都可以弄清楚它现在应该做什么(因为记住,它们遵循同一组指令!)。

“Exec”实际上是“execve()”。简而言之,它询问内核:“内核,请代替我(我是一个进程),具有 ______ 文件中指定的程序实例。”并且程序员还指定了论点新流程将具有的,以及环境它将拥有的(环境变量数组)。

因此,当你在 shell 中输入命令时,实际发生的情况(大多数情况下,忽略诸如 shell 内置命令之类的特殊情况cd)是你的 shell(一个正在运行的进程)叉子,进而执行官您指定的命令。

如果您已经完成了输出或输入重定向/bin/echo hello > /dev/null,那么分叉的子进程exec在 ing echo之前将相应地调整其文件描述符,以便文件描述符 1(在本例中)被绑定到/dev/null而不是您的终端或之前的任何位置。

所以是的,可执行文件的任何正在运行的实例/bin/bash都期望有一个可用的文件描述符 0(可以从中读取输入)、一个文件描述符 1(可以写入输出)以及一个文件描述符 2(可以读取和写入错误)消息和类似的输入/输出。

相关内容