【问题标题】:System calls, shell commands and programs系统调用、shell 命令和程序
【发布时间】:2013-04-04 02:26:04
【问题描述】:

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

当我在命令行上使用 C 编译器时,当我键入 cc [filename] ,我想外壳使用 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编译器等的其他进程??

我希望这听起来不会太令人困惑,因为我是 =/。

【问题讨论】:

    标签: shell executable system-calls


    【解决方案1】:

    是的!你明白了。

    当我在命令行上使用 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() 其他进程执行日期、cc 编译器等??

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 有趣..我不知道那些 PATH 变量...谢谢!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      • 2019-01-05
      • 2018-03-09
      相关资源
      最近更新 更多