你的理解是相当准确的. shell使用clone()系统调用来创建新进程.该联机帮助页描述了它与fork()的区别:
Unlike fork(2), clone() allows the child process to share parts of its
execution context with the calling process, such as the memory space,
the table of file descriptors, and the table of signal handlers.
(Note that on this manual page, “calling process” normally
corresponds to “parent process”.
然后,它使用execve()系统调用将当前子进程映像替换为新的进程映像.此系统调用是使进程运行程序代码的原因.
当一个进程分叉父文件描述符被复制.从fork(2)手册页:
The child inherits copies of the parent’s set of open file descriptors.
Each file descriptor in the child refers to the same open file
description (see open(2)) as the corresponding file descriptor in
the parent. This means that the two descriptors share open file
status flags, current file offset, and signal-driven I/O attributes
(see the description of F_SETOWN and F_SETSIG in fcntl(2)).
这就是当程序写入stdout时,文本显示在终端上的原因.您可以使用Linux中的strace程序查看此过程.以下是在Linux中对bash进程运行strace并在shell中执行/ bin / echo foo的主要摘录.
21:32:20 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f3f419f19d0) = 32036
Process 32036 attached
[pid 32017] 21:32:20 wait4(-1,
[pid 32036] 21:32:20 execve("/bin/echo", ["/bin/echo", "foo"], ["XDG_VTNR=8", "KDE_MULTIHEAD=false", "XDG_SESSION_ID=5512", "SSH_AGENT_PID=30259", "DM_CONTROL=/var/run/xdmctl", "TERM=xterm", "SHELL=/bin/bash", "XDM_MANAGED=method=classic", "XDG_SESSION_COOKIE=5c78dafb330601d94d7556bb52a6a2a6-1450467466.154128-547622992", "HISTSIZE=50000", "KONSOLE_DBUS_SERVICE=:1.160", "GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/jordan/.gtkrc-2.0:/home/jordan/.kde/share/config/gtkrc-2.0", "KONSOLE_PROFILE_NAME=Shell", "GTK_RC_FILES=/etc/gtk/gtkrc:/home/jordan/.gtkrc:/home/jordan/.kde/share/config/gtkrc", "GS_LIB=/home/jordan/.fonts", "WINDOWID=92274714", "SHELL_SESSION_ID=5b72a0038b0c4000a9299cae82f340a2", "KDE_FULL_SESSION=true", "USER=jordan", "SSH_AUTH_SOCK=/tmp/ssh-JEjo6RVmNhvR/agent.30205", "SESSION_MANAGER=local/tesla:@/tmp/.ICE-unix/30329,unix/tesla:/tmp/.ICE-unix/30329", "PATH=/home/jordan/.gem/ruby/1.9.1/bin:/home/jordan/.gem/ruby/1.9.1/bin:/home/jordan/bin:/home/jordan/local/packer:/home/jordan/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/local/sbin:/usr/sbin:/home/jordan/.rvm/bin:/home/jordan/prog/go/bin:/home/jordan/.rvm/bin:/home/jordan/prog/go/bin", "DESKTOP_SESSION=kde-plasma", "PWD=/home/jordan/games", "WORKING=/home/jordan/prog/greenspan", "KONSOLE_DBUS_WINDOW=/Windows/1", "EDITOR=emacs -nw", "LANG=en_US.UTF-8", "KDE_SESSION_UID=1000", "PS1=\[\033[01;32m\]\u@\h\[\033[01;34m\] \w\[\033[1;31m\]$(__git_ps1)\[\033[01;34m\] \$\[\033[00m\] ", "KONSOLE_DBUS_SESSION=/Sessions/1", "SHLVL=2", "XDG_SEAT=seat0", "COLORFGBG=15;0", "HOME=/home/jordan", "LANGUAGE=", "KDE_SESSION_VERSION=4", "GOROOT=/home/jordan/local/go", "XCURSOR_THEME=oxy-zion", "LOGNAME=jordan", "DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-onouV6Cc66,guid=bcdceeabe7aa00a28d55899f5674608a", "XDG_DATA_DIRS=/usr/share:/usr/share:/usr/local/share", "GOPATH=/home/jordan/prog/go", "PROMPT_COMMAND=history -a", "WINDOWPATH=8", "DISPLAY=:0", "XDG_RUNTIME_DIR=/run/user/1000", "PROFILEHOME=", "QT_PLUGIN_PATH=/home/jordan/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/", "XDG_CURRENT_DESKTOP=KDE", "HISTTIMEFORMAT=%F %T: ", "_=/bin/echo"]) = 0
[pid 32036] 21:32:20 write(1, "foo
", 4) = 4
[pid 32036] 21:32:20 exit_group(0) = ?
[pid 32036] 21:32:20 +++ exited with 0 +++
21:32:20 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WSTOPPED|WCONTINUED, NULL) = 32036