c - 程序如何继承环境变量?

标签 c linux libc

当我使用标准 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 by filename. [...] 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 form key=value, which are passed as environment to the new program. Both argv and envp 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/

相关文章:

c - 我想将一个函数拆分成两个函数

linux - Bash 脚本进程替换语法错误 : "(" unexpected

c - Solaris 11/Illumos/OmniOS : Which package has/usr/include/sys/types. h?

c - 我是否需要担心 Valgrind 报告超出我的应用程序范围的错误?

c - 一条 switch 语句占用多少代码空间?

c - linux 内核模块编译先决条件

java - 如何将独立的 Scala 应用程序转换为可运行的 SOA?

c - 注意到 linux 中的一个进程没有显示在进程列表中,这是怎么发生的?

c - 宏常量中的 float 学,同时保持整数性

linux - 无法在 Azure 上的 Ubuntu 16.04 上连接 Percona Docker 镜像