当我使用标准 C 库中的函数 getenv()
时,我的程序从其父程序继承了环境变量。
例子:
$ export FOO=42
$ <<< 'int main() {printf("%s\n", getenv("FOO"));}' gcc -w -xc - && ./a.exe
42
在 libc 中,environ
变量被声明到 environ.c
中。我希望它在执行时为空,但我得到 42
。
更进一步getenv
可以简化如下:
char * getenv (const char *name)
{
size_t len = strlen (name);
char **ep;
uint16_t name_start;
name_start = *(const uint16_t *) name;
len -= 2;
name += 2;
for (ep = __environ; *ep != NULL; ++ep)
{
uint16_t ep_start = *(uint16_t *) *ep;
if (name_start == ep_start && !strncmp (*ep + 2, name, len)
&& (*ep)[len + 2] == '=')
return &(*ep)[len + 3];
}
return NULL;
}
libc_hidden_def (getenv)
这里我只获取__environ
变量的内容。但是我从来没有初始化它。
所以我很困惑,因为 environ
应该是 NULL
除非我的 main 函数不是我程序的真正入口点。也许 gcc
通过添加作为标准 C 库一部分的 _init
函数来吸引我。
environ
在哪里初始化?
最佳答案
环境变量作为 第三个参数从父进程传递到 main
。发现这一点的最简单方法是阅读系统调用的文档 execve
,尤其是这一点:
int execve(const char *filename, char *const argv[], char *const envp[]);
Description
execve()
executes the program pointed to byfilename
. [...]argv
is an array of argument strings passed to the new program. By convention, the first of these strings should contain the filename associated with the file being executed.envp
is an array of strings, conventionally of the formkey=value
, which are passed as environment to the new program. Bothargv
andenvp
must be terminated by a NULL pointer. The argument vector and environment can be accessed by the called program's main function, when it is defined as:int main(int argc, char *argv[], char *envp[])
C 库在调用 main
之前将 envp
参数复制到其启动代码中某处的 environ
全局变量中:例如, GNU libc 在 _init
中执行此操作musl libc 在 __init_libc
中做到了. (您可能会发现 musl libc 的代码比 GNU libc 的代码更容易跟踪。)相反,如果您使用 exec
之一启动程序不采用显式环境 vector 的包装函数,C 库提供environ
作为execve
的第三个参数。因此,环境变量的继承是严格的用户空间约定。就内核而言,每个程序接收两个参数 vector ,并且它不关心它们中的内容。
(注意三参数main
是对C语言的扩展,C标准只规定了int main(void)
和int main(int argc, char **argv)
但它允许实现定义额外的形式( C11 Annex J.5.1 Environment Arguments )。三参数 main
自 Unix V7 以来一直是环境变量的工作方式,如果不是更长的话,并且也由 Microsoft 记录 — 请参阅 What should main()
return in C and C++?。)
关于c - 程序如何继承环境变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31034993/