在不移动整个用户堆栈的情况下,putenv/ setenv如何工作?

问题描述

在这里阅读了几篇文章,但仍然对setenv()的工作方式感到困惑:

我的理解是环境变量作为一堆“ foo = bar \ 0”字符串连续存储在用户堆栈的底部,然后有一个指向这些字符串的指针数组envp[] ,也靠近用户堆栈的底部用户堆栈在这些字节的顶部增长,这意味着向字符串区域或指针数组添加更多内容并非易事。因此,如果设置了新变量(需要向setenv()添加元素),或者更改了变量但新值字符串长于旧变量,envp[]的工作原理修改是不可能的),而又不会(几乎)转移整个用户堆栈为新来者腾出空间?

一个相关的问题是,bash是否保留本地设置变量的内部列表,并且当用户export本地设置变量时,bash只是将其从此本地管理列表中删除,并将其添加到上面提到的堆栈字符串区域的底部,并将其指针插入指针数组envp[],以便其子进程自动继承导出的变量?

解决方法

我的理解是环境变量存储为...

您的理解仅部分正确。 :微笑:

......没有(几乎)转移整个用户堆栈为新来者腾出空间吗?

那是不可能的。不管程序编写的语言是C还是操作系统是UNIX。例如,由于堆栈上的指针可以引用堆栈上的其他位置。

首先要注意的是,环境变量在新进程中的存储位置取决于体系结构。如您所述,在大多数CPU体系结构上,大多数UNIX实现将其存储在堆栈中。但是,在C规范中实际上没有任何东西可以强制执行该解决方案。同样,如果您修改环境,则实现可以自由地将现有环境var的块复制到内存中的新位置。 C实现可以自由移动env var块并更新魔术__environ var。

一个有点相关的问题是,bash是否保留了本地设置变量的内部列表...。

与您描述的方式不同。它确实保留了本地设置变量的“内部列表”。但是它没有按照您的建议使用它。

我很好奇是什么促使您打开此问题的