在 Bash 中执行的新进程如何始终具有相同的环境变量?

swe*_*ion 2 bash process environment-variables elf linux-kernel

不久前,我正在使用 GDB 探索一个简单的 C 程序的 ELF 二进制文件。我看到我printenv在终端中运行时打印的环境变量也出现在我在该终端中运行的 C 程序二进制文件的堆栈顶部。

Bash 如何实际执行程序,同时所有环境变量也被添加到新进程的堆栈中?简而言之,当我运行这样的程序时会发生什么: ./myprogram

Joh*_*éen 5

使用execve系统调用执行 Linux 程序。execve具有以下签名:

int execve(const char *filename, char *const argv[], char *const envp[]);
Run Code Online (Sandbox Code Playgroud)

最后一个参数envp用于将环境作为字符串数组传递给进程,每个字符串的形式为 key=value。按照惯例,相同的环境从一个进程传递到另一个进程,除非调用进程对其进行一些更改。内核安排新程序接收堆栈上的环境,与传递程序参数的方式相同。

库函数execlexeclpexecvexecvp不接受envp参数(但execleexecvpe函数接受)。这些函数从environ调用过程中的全局变量中获取环境。这样一个程序使用该execle函数启动另一个程序就不必担心传递环境,但库函数会在“幕后”自动完成。

所有提到的库函数最终都会调用execve系统调用,并在envp参数中传递环境。