4

プログラム、シェル コマンド、およびオペレーティング システムがどのように機能するかを理解しようとしています。初心者なので無知ですみません。

コマンド ラインで C コンパイラを使用する場合、 cc [filename] と入力すると、シェルが fork() システム コールを使用してプロセスを複製し、exec() システム コールが cc コンパイラ実行可能ファイルを子プロセスのコア イメージ。次に、シェルを実行している親プロセスが待機している間、cc 実行可能ファイルを含む子プロセスが処理を実行します。そうですか?

cp、mv、ls などのシェル コマンドはどうでしょうか。彼らは何ですか?それらは、シェルによってフォークされた新しい子プロセスでも実行される実行可能プログラムですか? シェルスクリプトはどうですか?次のような単純なシェル スクリプトを作成するとします (まだ方法がわからないエラーは無視してください)。

echo "Hello" 

date

echo

cc -o test file1.c file2.c file3.c

次に、コマンド ラインを使用してこのスクリプトを実行します。コマンドラインは新しいプロセスを fork() し、新しいプロセスでこのスクリプトを exec() しますか? そして、スクリプト fork() を含むこの新しいプロセスは、日付、cc コンパイラなどを実行する他のプロセスを実行しますか??

私は=/なので、これがあまり混乱しないことを願っています。

4

2 に答える 2

6

うん!あなたはアイデアを持っています。

コマンド ラインで C コンパイラを使用する場合、 cc [filename] と入力すると、シェルが fork() システム コールを使用してプロセスを複製し、exec() システム コールが cc コンパイラ実行可能ファイルを子プロセスのコア イメージ。次に、シェルを実行している親プロセスが待機している間、cc 実行可能ファイルを含む子プロセスが処理を実行します。そうですか?

それは正しい。親プロセス (シェル) はwait()、子の PID を呼び出し、終了するのを待ちます。

cp、mv、ls などのシェル コマンドはどうでしょうか。彼らは何ですか?それらは、シェルによってフォークされた新しい子プロセスでも実行される実行可能プログラムですか?

同じこと。これらはコンパイラのようなバイナリであり、シェルはそれらに対して同じことを行います。

現在、「ビルトイン」と呼ばれる外部バイナリではないコマンドがいくつかあります。これらは、シェルがそれ自体を認識するコマンドであり、外部バイナリを呼び出す必要はありません。なんで?

  • ifandのような特別な構文を持つものもあるwhileため、必然的にシェルに組み込む必要があります。
  • cdやなどの一部はread、シェル プロセスの状態を変更するため、組み込みである必要があります。(外部バイナリがシェルの現在のディレクトリを変更することは不可能です。フォークされたプロセスは、親の PWD ではなく、自身の PWD しか変更できないためです。)
  • echoやのような他のものは、printf別個のバイナリである可能性があり、たまたまシェルによって実装されているだけです。

入力から取得した bash ビルトインの完全なリストを次に示しますhelp

 job_spec [&]                                                          history [-c] [-d offset] [n] or history -anrw [filename] or histor>
 (( expression ))                                                      if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [>
 . filename [arguments]                                                jobs [-lnprs] [jobspec ...] or jobs -x command [args]
 :                                                                     kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill>
 [ arg... ]                                                            let arg [arg ...]
 [[ expression ]]                                                      local [option] name[=value] ...
 alias [-p] [name[=value] ... ]                                        logout [n]
 bg [job_spec ...]                                                     mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callbac>
 bind [-lpvsPVS] [-m keymap] [-f filename] [-q name] [-u name] [-r k>  popd [-n] [+N | -N]
 break [n]                                                             printf [-v var] format [arguments]
 builtin [shell-builtin [arg ...]]                                     pushd [-n] [+N | -N | dir]
 caller [expr]                                                         pwd [-LP]
 case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac            read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars>
 cd [-L|[-P [-e]]] [dir]                                               readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callb>
 command [-pVv] command [arg ...]                                      readonly [-aAf] [name[=value] ...] or readonly -p
 compgen [-abcdefgjksuv] [-o option]  [-A action] [-G globpat] [-W w>  return [n]
 complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G gl>  select NAME [in WORDS ... ;] do COMMANDS; done
 compopt [-o|+o option] [-DE] [name ...]                               set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
 continue [n]                                                          shift [n]
 coproc [NAME] command [redirections]                                  shopt [-pqsu] [-o] [optname ...]
 declare [-aAfFgilrtux] [-p] [name[=value] ...]                        source filename [arguments]
 dirs [-clpv] [+N] [-N]                                                suspend [-f]
 disown [-h] [-ar] [jobspec ...]                                       test [expr]
 echo [-neE] [arg ...]                                                 time [-p] pipeline
 enable [-a] [-dnps] [-f filename] [name ...]                          times
 eval [arg ...]                                                        trap [-lp] [[arg] signal_spec ...]
 exec [-cl] [-a name] [command [arguments ...]] [redirection ...]      true
 exit [n]                                                              type [-afptP] name [name ...]
 export [-fn] [name[=value] ...] or export -p                          typeset [-aAfFgilrtux] [-p] name[=value] ...
 false                                                                 ulimit [-SHacdefilmnpqrstuvx] [limit]
 fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]      umask [-p] [-S] [mode]
 fg [job_spec]                                                         unalias [-a] name [name ...]
 for NAME [in WORDS ... ] ; do COMMANDS; done                          unset [-f] [-v] [name ...]
 for (( exp1; exp2; exp3 )); do COMMANDS; done                         until COMMANDS; do COMMANDS; done
 function name { COMMANDS ; } or name () { COMMANDS ; }                variables - Names and meanings of some shell variables
 getopts optstring name [arg]                                          wait [id]
 hash [-lr] [-p pathname] [-dt] [name ...]                             while COMMANDS; do COMMANDS; done
 help [-dms] [pattern ...]                                             { COMMANDS ; }

ビルトインの他に、関数とエイリアスもあります。これらは、個別のスクリプト/バイナリを作成することなく、新しい機能を定義する方法です。

uppercase() {
    tr '[:lower:]' '[:upper:]' <<< "$*"
}

alias ls='ls --color=auto -F'

関数とエイリアスは通常、利便性のためか、補助機能を追加するためのものです。

シェルスクリプトはどうですか?... コマンドラインは新しいプロセスを fork() し、新しいプロセスでこのスクリプトを exec() しますか? そして、スクリプト fork() を含むこの新しいプロセスは、日付、cc コンパイラなどを実行する他のプロセスを実行しますか??

はい、まさにその通りです。シェル スクリプトが実行されると、親シェルが子プロセスをフォークし、そこでスクリプトが実行されます。スクリプト内のコマンドは、したがって、この子プロセスからフォークされました。それらは元のシェルの孫です。

于 2013-04-11T18:56:10.190 に答える
3

シェルスクリプトを実行すると、フォークして新しいシェルが作成され、個別のフォーク/実行メカニズムを介して各コマンドが解釈されます。ただし、いくつかのシェル ビルトインがあります。たとえば、/usr/bin で実行可能ファイルとして使用できる場合でも、一部のシェルに echo が組み込まれている場合があります。cp と mv は、実際には fork/exec メカニズムを介して実行される実行可能ファイルです。見逃しているかもしれないことの 1 つは、実行可能ファイルがPATH変数に含まれるディレクトリにある必要があることです。現在のディレクトリにある hello world コードの実行可能ファイルの名前を に変更し、ls現在のディレクトリ (.) をパスの最初のディレクトリとして指定してみてください。typeおよびwhichコマンドを使用して、実行可能ファイルについて調べることもできます。

于 2013-04-11T19:00:20.873 に答える