根据我的理解,环境变量的值直接在以NULL结尾的argv值之后存储在内存中.除了env变量之外,auxv还存在.
环境变量究竟是如何布局的 - 指定/记录此布局的位置?它适用于哪些系统?
一个简单的答案是:程序调用的堆栈布局由二进制格式定义定义(例如ELF规范:http://refspecs.linuxbase.org/elf/abi386-4.pdf,请参见图3- 31为初始堆栈布局exec).
由于Linux不仅限于ELF可执行文件,并且可以使用其binfmt解释器框架支持多种二进制格式,因此argv/ envpdata 的实际处理分两个阶段进行.
首先,当sys_execve调用系统调用时,内核将为新进程堆栈创建虚拟内存映射.然后它将从堆栈底部使用一个或几个页面(最多32页任意限制)来存储所提供的argv/ envp参数的副本:
bprm->exec = bprm->p;
retval = copy_strings(bprm->envc, envp, bprm);
if (retval < 0)
goto out;
retval = copy_strings(bprm->argc, argv, bprm);
if (retval < 0)
goto out;
Run Code Online (Sandbox Code Playgroud)
(http://code.metager.de/source/xref/linux/stable/fs/exec.c#1502)
在第二阶段,将bprm对象传递给binfmt解释器(以及相关的内存映射).除了其他内容之外,解释器还会将其他信息推送到堆栈,包括参数/环境条目计数和指针.对于精灵可执行文件,它将发生在create_elf_tables:
/* Now, let's put argc (and argv, envp if appropriate) on the stack */
if (__put_user(argc, sp++))
return -EFAULT;
argv = sp;
envp = argv + argc + 1;
/* Populate argv and envp */
p = current->mm->arg_end = current->mm->arg_start;
while (argc-- > 0) {...
Run Code Online (Sandbox Code Playgroud)
(http://code.metager.de/source/xref/linux/stable/fs/binfmt_elf.c#293)
这里的解释器实际上是在上面链接的规范中构建图3-31中概述的结构.