【问题标题】:Memory layout of argc, argv, envpargc、argv、envp的内存布局
【发布时间】:2014-06-29 06:26:34
【问题描述】:

据我了解,环境变量的值直接位于内存中以 NULL 结尾的 argv 值之后。除了 env 变量之外,还存在 auxv

环境变量的布局究竟是怎样的——这个布局是在哪里指定/记录的?它适用于哪些系统?

【问题讨论】:

    标签: c linux


    【解决方案1】:

    一个简单的答案是:程序调用时的堆栈布局由二进制格式定义定义(例如 ELF 规范:http://refspecs.linuxbase.org/elf/abi386-4.pdfexec 上的初始堆栈布局请查看图 3-31) .

    由于 Linux 不限于 ELF 可执行文件,并且可以使用其 binfmt 解释器框架支持多种二进制格式,因此 argv/envp 数据的实际处理分两个阶段进行。

    首先,当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;
    

    (http://code.metager.de/source/xref/linux/stable/fs/exec.c#1502)

    在第二阶段,bprm 对象被传递给binfmt 解释器(连同相关的内存映射)。解释器,除其他外,会将附加信息推送到堆栈,包括参数/环境条目计数和指针。对于 elf 可执行文件,它将发生在 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) {...
    

    (http://code.metager.de/source/xref/linux/stable/fs/binfmt_elf.c#293)

    这里的解释器实际上是在构建上面链接的规范中图 3-31 中概述的结构。

    【讨论】:

    • 所以澄清一下,听起来我希望拥有这种布局的只有 ELF 二进制文件?
    • 是的,这取决于特定的二进制格式。 A.out 不同,“平面”可执行文件也不同。
    猜你喜欢
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 2013-02-02
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 2020-11-03
    相关资源
    最近更新 更多