単純なコマンドの実行に関する簡単な質問があります。私が理解したのは、インタラクティブls
シェルにコマンドを入力すると
- シェルはコマンドを解釈します。
- Shell は子プロセスを作成し、子プロセスでコマンドを実行します。
- シェルは子プロセスが完了するのを待ちます。
私の理解が正しい場合は、シェルプロンプトに入力する単純なコマンドは子プロセスで実行され、コマンドの結果は現在のシェル環境には影響しません。
それでは、このような組み込みコマンドはどうですかcd
?現在のシェルの作業ディレクトリがcd
子プロセスで実行され、現在のシェル環境に影響を与えない場合、どのように変更できますか?
答え1
シェルは単なるプログラムですが、システムで重要な役割を果たします。 Bashと他のほとんどの一般的なシェルはCで実装されています。最も重要な2つのネイティブCシステムコール子プロセスを作成するために使用されるプロセスfork()
はとですexec()
。これらの機能は通常、シェルを含む高級言語でも実装されています。
fork()
「フォーク」は、呼び出しプロセスのコピーを子プロセスにします。これは、最初のプロセスを除くシステムのほぼすべてのプロセスがどのように機能するかです(内部に)開始:これを開始したプロセスのコピー。シェル言語には実際には機能がありませんが、
fork
同じサブシェルを生成するための構文が含まれています。exec()
Cには実際には呼び出しはありませんが、
exec()
関連する関数グループを語句として参照します。man 3 exec
通常、次から始まるthisとしてリストを見ることができます。exec() 関数シリーズは、現在のプロセスイメージを新しいプロセスイメージに置き換えます。
これが正確に行うことです。変える実行可能ファイル(たとえば)から
/usr/bin/ls
ロードされた新しいコンテンツを使用して、現在のプロセスのメモリスタック部分を定義します。これがfork()
新しいプロセスを作成するときに最初にこれを行う必要がある理由です。そうしないと、呼び出しプロセスは以前のプロセスから外れ、他のプロセスは実際には作成されません。
一見すると、これはとんでもなく非効率的な作業方法のように聞こえるかもしれません。コマンドを使用して最初から新しいプロセスを作成するのはどうですか?実際、これは次のようないくつかの理由でそれほど効果的ではない可能性があります。
fork()
カーネルが使用するように、結果の「コピー」はやや抽象的です。書き込み中のコピー実際に作成する必要があるのは仮想メモリマップだけです。 copy が直ちに呼び出される場合exec()
、プロセスのアクティビティがデータを変更してもほとんどのデータは実際にコピー/生成される必要はありません。プロセスは、データの使用に必要な操作を実行しないためです。サブプロセスの重要な側面(たとえば、その環境)は、個別にコピーしたり、コンテキストなどの複雑な分析に基づいて設定する必要はありません。彼らは呼び出しプロセスと同じであると仮定し、これは私たちになじみのあるかなり直感的なシステムです。
生成された子プロセスに「環境コピー」が正確に何を意味するのかについての詳細は、以下を参照してください。私の答えはここにあります。
それでは、cdのような組み込みコマンドはどうですか?
繰り返しますが、Cでのみ実装されます。と同様chdir()
に、これは標準CのUnixプラットフォーム拡張の一部であり、シェルコマンドの基礎です。から:fork()
exec()
cd
man 2 chdir
chdir() 呼び出しプロセスの現在の作業ディレクトリをPATHで指定されたディレクトリに変更します。
これは子プロセスを必要とせず、呼び出し側に影響を与えます。シェルは対話型ランタイムです。通訳これは、コマンドを実行するとシェル言語で書かれたコードを実行することを意味します。通常、これを行うために新しいプロセスを実行する必要はなく、それ自体を実行します。
答え2
それでは、cdのような組み込みコマンドはどうですか? cd が子プロセスで実行される場合
ロジックのエラーはここにあります。cd
これは、シェルによって特別に解釈され、プロセス内で「実行される」シェル組み込みコマンドです。このtype
コマンドを使用して、コマンドが組み込みコマンドであるかどうかを確認できます。