系统调用,shell命令和程序

时间:2013-04-11 18:46:08

标签: shell executable system-calls

我正在尝试了解程序,shell命令和操作方式 系统工作。请原谅我的无知,因为我是新手。

当我在命令行上使用C编译器时,我输入cc  [filename],我想shell使用fork()系统调用 复制其进程,然后exec()系统调用将加载 cc编译器可执行文件进入子进程的核心映像。那么 包含cc可执行文件的子进程将执行其中的操作 执行shell的父进程是否等待。是不是?

如cp,mv,ls等shell命令怎么样?这些是什么? 他们是可执行程序,也将以新的方式执行 子进程由shell分叉? shell脚本怎么样?假设我创建了一个简单的shell脚本 喜欢这个(请忽略任何错误,我不知道如何做到这一点 然而):

echo "Hello" 

date

echo

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

然后我使用命令行执行此脚本。请问 命令行fork()一个新进程和exec()这个脚本在新的 处理?然后这个包含脚本fork()的新进程 执行日期,cc编译器等的其他进程??

我希望这听起来不会太混乱,因为我= =。

2 个答案:

答案 0 :(得分:5)

是的!你有这个主意。

  

当我在命令行上使用C编译器时,当我输入cc [filename]时,我认为shell使用fork()系统调用来复制其进程,然后exec()系统调用将加载cc编译器可执行到子进程的核心映像。然后,包含cc可执行文件的子进程将执行其操作,而执行shell的父进程是否等待。是不是?

没错。父进程(shell)在子进程的PID上调用wait()并等待它退出。

  

如cp,mv,ls等shell命令怎么样?这些是什么?它们是可执行程序,也将在shell分叉的新子进程中执行吗?

同样的事情。这些是二进制文件,就像编译器一样,shell也为它们做同样的事情。

现在有些命令不是外部二进制文件,称为“内置函数”。这些是shell识别自身的命令,不需要为外部二进制文件调用。为什么呢?

  • 有些语法具有特殊语法,例如ifwhile,因此必须在shell中构建。
  • 有些像cdread一样,会更改shell进程的状态,因此必须是内置函数。 (外部二进制文件不可能更改shell的当前目录,因为分叉进程只能更改自己的PWD,而不能更改它们的父进程。)
  • 其他人,如echoprintf,可能是单独的二进制文件,恰好由shell实现。

以下是我在输入help时获得的bash内置的完整列表:

 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'

函数和别名通常是为了方便或添加补充功能。

  

shell脚本怎么样? ...命令行fork()一个新进程和exec()这个脚本在新进程中?然后这个新进程将包含脚本fork()其他进程来执行date,cc编译器等等吗?

是的,完全正确。运行shell脚本时,父shell会分叉子进程,并且脚本在那里运行。脚本中的命令因此分离出这个子进程;他们是原始贝壳的孙子。

答案 1 :(得分:2)

当你执行一个shellcript时,它会分叉并创建一个新shell,通过一个单独的fork / exec机制解释每个命令。但是,有一些shell内置,例如,即使在/ usr / bin中可用作可执行文件,echo也可以内置到某些shell中。 cp和mv确实是通过fork / exec机制执行的可执行文件。您可能错过的一件事是可执行文件需要位于PATH变量中包含的目录中。尝试将当前目录中的hello world代码可执行文件重命名为ls,并将当前目录(。)指定为路径中的第一个目录。您还可以使用typewhich命令查找可执行文件。