为什么 /proc 文件系统中 environ 的内容与 extern environ 指向的内容不同?

Why the contents of environ in the /proc file system differs from what extern environ pointed to?

我的 C++

getenv() apache/cgi 给了我奇怪的东西,然后我检查了 /proc/${PID_OF_THE_RUNNING_PROCESS} 中的环境,它们不匹配,我认为它们应该匹配,我想知道 /proc 出了什么问题,或者是 getenv()?

shell@kernel # xargs --null --max-args=1 echo < /proc/${PID_OF_THE_RUNNING_PROCESS}/environ 
PATH=/usr/bin:/bin:/usr/sbin:/sbin
LD_LIBRARY_PATH=/usr/local/httpd-2.2.19/lib:

代码PID_OF_THE_RUNNING_PROCESS

#include<stdio.h>
extern char **environ;

void run()
{
    char* s = *environ;
    printf("declare -x  all env begin\n");    
    for (int i = 1; NULL != s; ++i) {
        printf("declare -x  %s\n", s);
        s = *(environ+i);
    }
    printf("declare -x  all env end\n");
}

PID_OF_THE_RUNNING_PROCESS

的控制台日志
declare -x  all env begin
declare -x  FCGI_ROLE=RESPONDER
declare -x  UNIQUE_ID=Wvq-Cn8AAAEAAAkmJlsAAAmM
declare -x  HTTP_HOST=www.example.com
declare -x  HTTP_X_CLIENT_PROTO=https
declare -x  HTTP_X_CLIENT_PROTO_VER=HTTP/1.1
declare -x  HTTP_X_REAL_IP=112.96.194.222
declare -x  HTTP_X_FORWARDED_FOR=112.96.194.222
declare -x  CONTENT_LENGTH=177
declare -x  HTTP_CHARSET=utf-8
declare -x  HTTP_ACCEPT_ENCODING=gzip
declare -x  HTTP_REFERER=https://serviceexample.com/exbb58374cdce267a6/91/page-frame.html
declare -x  CONTENT_TYPE=application/x-www-form-urlencoded
declare -x  HTTP_USER_AGENT=Mozilla/5.0 (Linux; Android 5.1; vivo X6Plus D Build/LMY47I; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044030 Mobile Safari/537.36 MicroMessenger/6.6.6.1300(0x26060637) NetType/4G Language/zh_CN MicroMessenger/6.6.6.1300(0x26060637) NetType/4G Language/zh_CN
declare -x  PATH=/usr/bin:/bin:/usr/sbin:/sbin
declare -x  SERVER_SIGNATURE=
declare -x  SERVER_SOFTWARE=Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/1.0.1t DAV/2 mod_fcgid/2.3.9
declare -x  SERVER_NAME=www.example.com
declare -x  SERVER_ADDR=10.241.94.209
declare -x  SERVER_PORT=80
declare -x  REMOTE_ADDR=10.56.81.214
declare -x  DOCUMENT_ROOT=/data/doc/www.example.com/htdocs
declare -x  SERVER_ADMIN=webmaster@tencent.com
declare -x  SCRIPT_FILENAME=/data/doc/www.example.com/cgi-bin/ex/common/www_ex_time.cgi
declare -x  REMOTE_PORT=46151
declare -x  GATEWAY_INTERFACE=CGI/1.1
declare -x  SERVER_PROTOCOL=HTTP/1.1
declare -x  REQUEST_METHOD=POST
declare -x  QUERY_STRING=
declare -x  REQUEST_URI=/cgi-bin/ex/common/www_ex_time.cgi
declare -x  SCRIPT_NAME=/cgi-bin/ex/common/www_ex_time.cgi
declare -x  HTTP_CONNECTION=close
declare -x  all env end
declare -x  112.96.194.222

是的,我找到了答案,如果进程在 运行-time 期间更改了环境,它们是不一样的。
我找到了官方文档here

/proc/[pid]/environ
              This file contains the initial environment that was set when
              the currently executing program was started via execve(2).              
              ......
              If, after an execve(2), the process modifies its environment
              (e.g., by calling functions such as putenv(3) or modifying the
              environ(7) variable directly), this file will not reflect
              those changes.

请注意初始环境 开始
我们将 env 更改为 setenv(),这将反映在 extern environ 上,我们可以通过验证它,但是 /proc/self/environ,它们是静态的,在运行-时间内不会受到影响。

/proc/$pid/environ 数据显示进程启动时环境变量的状态。如果环境变量随后被修改(例如,通过 putenv()),这将反映在 getenv() 的 return 值中,而不是 /proc/$pid/environ。您可以通过在一个终端中编译和 运行 以下程序并在另一个终端中查看它的 proc/.../environ 来查看实际效果。

#include <stdio.h>
#include <stdlib.h>

int main() {
    putenv("HOME=WTF");
    char *home = getenv("HOME");
    printf("pid %d  HOME=%s\n", getpid(), home);
    sleep(300);
}

P.S., 理论上对环境的更新可以反映在 /proc/$pid/environ 但实际上我不知道任何这样做的实现。