たとえば、コマンドを実行すると、test -l --hello check
シェル
はコマンドを変数に保存し、シェルはそのバイナリを$0="test"
実行し、$1="-l"
バイナリは変数を読み取り、バイナリは変数が言うように実行します。$2="--hello"
$3="check"
標準ストリームはまさにこれらの変数ですか?
@philip-coulingに質問します(コメントが限られているのでここに質問します):
リダイレクト演算子とパイプ(<、>、|)について問い合わせたいと思います。
はい、標準ストリームこれがリダイレクトとパイプの動作方法です。そうですか?
テキスト行をパラメータで除算する
これはコマンド自体だけでなく、パラメータ/フラグも保存します。たとえば、lsはコマンド部分、-laはパラメータ部分です。これは重要です。たとえば、ビジボックスの場合、これはバイナリにすぎず、通常はシンボリックリンクを使用して呼び出されます(たとえば、/ bin / ls(パスからls)を実行すると/ bin / busyboxへのシンボリックリンクです。必要なコマンドとそのフラグを知る方法)
配列としてコマンドに渡される
配列として? $0..$last変数を使用しませんか?
読み取りまたは書き込みのためにファイルを開くと、オペレーティングシステムは単純な数値である「ファイル記述子」を提供します。子プロセスは親プロセスからファイル記述子を継承します。親アイテムで開かれたすべてのファイルは、子アイテムでも開いて使用できます(ファイルを開かないように明示的な指示なしにファイルを開いていない場合)。
各ファイル記述子は数字だけです。最初の3つはstdin(0)stdout(1)stderr(2)用です。 posixのSTDERR_FILENOを参照してください。私が知っている限り、これは技術的に予約されていませんが、通常、これら3つの記述子が存在するという事実により、他の人が同じ番号を使用するのを防ぎます。
ソフトウェア言語には標準出力(たとえば、echoやprint)に書き込むための特別な構文があるかもしれませんが、実際にはすべてのバイナリが行うことはファイル記述子番号0に書き込むことです。
ああ、これはファイル記述子とstdin、stdout、stderrが0、1、2であることを覚えています。これらの説明は本当に良いです!ところで、問題は、コマンドの出力が両方とも1と2になるということです。そうですか?では、1番と2番はいつクリアされますか?
ベストアンサー1
<
リダイレクト演算子とパイプ(、、、>
)について問い合わせたいと思います|
。
コマンドライン引数の場合、シェルはテキスト行を引数で除算してコマンドに配列として渡されます。シェル呼び出しは、fork
新しいプロセスを作成し、新しいexec
コマンドを起動して引数を渡すために使用されます。
リダイレクトの場合、状況はもう少し複雑です。ファイル名は直接渡されません。代わりに、標準ストリームは親プロセスから継承され、シェルはおよび間fork
でそれらを変更する必要がありますexec
。
読み取りまたは書き込みのためにファイルを開くと、オペレーティングシステムは単純な数値である「ファイル記述子」を提供します。子プロセスは親プロセスからファイル記述子を継承します。親アイテムで開かれたすべてのファイルは、子アイテムでも開いて使用できます(ファイルを開かないように明示的な指示なしにファイルを開いていない場合)。
各ファイル記述子は数字だけです。最初の3つはstdin(0)stdout(1)stderr(2)用です。バラよりSTDERR_FILENOPOSIXでは。私が知っている限り、これは技術的に予約されていませんが、通常、これら3つの記述子が存在するという事実により、他の人が同じ番号を使用するのを防ぎます。
echo
ソフトウェア言語には標準出力に書き込むための特別な構文(たとえば、または)がありますが、print
実際にはバイナリが実行する作業はファイル記述子番号0に書き込むだけです。
リダイレクト演算子がどのように機能するかは、シェルがファイルを開くかファイルディスクリプタをインポートするためのパイプを作成し、それを呼び出すdup2
前にディスクリプタを3つ(0,1,2)のいずれかにコピーすることですexec
。
したがって、子プロセスはstdin、stdout、またはstderrで開かれている内容を決して知りません。ファイル記述子しかないので、オペレーティングシステムに要求するとより多くの情報を得ることができます。