问题描述
我在这里阅读了几篇文章,但仍然对setenv()
的工作方式感到困惑:
- linux-where-are-environment-variables-stored
- where-is-the-environment-string-actual-stored
- how-do-i-program-my-own-setenv
我的理解是环境变量作为一堆“ foo = bar \ 0”字符串连续存储在用户堆栈的底部,然后有一个指向这些字符串的指针数组envp[]
,也靠近用户堆栈的底部。用户堆栈在这些字节的顶部增长,这意味着向字符串区域或指针数组添加更多内容并非易事。因此,如果设置了新变量(需要向setenv()
添加元素),或者更改了变量但新值字符串长于旧变量,envp[]
的工作原理修改是不可能的),而又不会(几乎)转移整个用户堆栈为新来者腾出空间?
一个相关的问题是,bash
是否保留本地设置变量的内部列表,并且当用户export
本地设置变量时,bash
只是将其从此本地管理列表中删除,并将其添加到上面提到的堆栈字符串区域的底部,并将其指针插入指针数组envp[]
,以便其子进程自动继承导出的变量?
解决方法
我的理解是环境变量存储为...
您的理解仅部分正确。 :微笑:
......没有(几乎)转移整个用户堆栈为新来者腾出空间吗?
那是不可能的。不管程序编写的语言是C还是操作系统是UNIX。例如,由于堆栈上的指针可以引用堆栈上的其他位置。
首先要注意的是,环境变量在新进程中的存储位置取决于体系结构。如您所述,在大多数CPU体系结构上,大多数UNIX实现将其存储在堆栈中。但是,在C规范中实际上没有任何东西可以强制执行该解决方案。同样,如果您修改环境,则实现可以自由地将现有环境var的块复制到内存中的新位置。 C实现可以自由移动env var块并更新魔术__environ
var。
一个有点相关的问题是,bash是否保留了本地设置变量的内部列表...。
与您描述的方式不同。它确实保留了本地设置变量的“内部列表”。但是它没有按照您的建议使用它。
我很好奇是什么促使您打开此问题的