Linuxshell如何获取$的return码值?多变的?

How does the Linux shell get the return code value for $? variable?

Linux shell 是否执行 fork/exec 然后 waitpid() 以获得 return 代码来填充 $?变量,每次它执行什么?

是的,这正是它的作用。

如果您有兴趣,可以通过 strace 下的 运行 shell(一种拦截并打印程序发出的所有系统调用的工具)亲自查看。

strace bash -c '/usr/bin/ls > /dev/null; echo $?'

这给出了以下输出,经过大量修剪:

execve("/usr/bin/bash", ["bash", "-c", "/usr/bin/ls > /dev/null; echo $?"], [/* 58 vars */]) = 0
[....]
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7ff16c3d69d0) = 1189
[....]
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 1189
[....]
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1189, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
wait4(-1, 0x7ffd3096b290, WNOHANG, NULL) = -1 ECHILD (No child processes)
[....]
exit_group(0)                           = ?
+++ exited with 0 +++

我使用了一个带有两个命令的 bash 脚本,否则 bash 不会分叉,而只是执行命令,替换自身(我刚刚发现的一个有用的优化!)

在输出中,clonefork函数背后的系统调用,同样wait4waitpid调用。您看不到 exec,因为它发生在子进程中,我们没有要求 strace 进行跟踪。如果你添加 -f 那么它会这样做,但也会跟踪 ls 进程的内容。