Skip to main content

环境变量是什么

· 3 min read

当我们使用shell 的命令env命令的时候可以看到很多字符串,那些就是这个进程的环境变量

环境变量怎么存

The first two arguments are just the same. The third argument envp gives the program’s environment; it is the same as the value of environ. See Environment Variables. POSIX.1 does not allow this three-argument form, so to be portable it is best to write main to take two arguments, and use the value of environ.

posix 相关文档

where argc is the argument count and argv is an array of character pointers to the arguments themselves. In addition, the following variable:

extern char **environ;

is initialized as a pointer to an array of character pointers to the environment strings. The argv and environ arrays are each terminated by a null pointer. The null pointer terminating the argv array is not counted in argc.

例子

下面是例子

#include <stdio.h>

extern char **environ;

int main(int argc, const char *argv[]) {
printf("environment variables:\n");
int i = 0;
while (environ[i]) {
printf("%p\t%s\n", environ[i], environ[i]);
i++;
}

printf("argv:\n");
for (int i = 0; i < argc; i++) {
printf("%p\t%s\n", argv[i], argv[i]);
}
}

编译后会把这些打印出来

gcc main.c -o main
dinosaur@dinosaur-X550VXK:~/test$ ./main
environment variables:
0x7ffc250920c7 XDG_VTNR=7
0x7ffc250920d2 LC_PAPER=zh_CN.UTF-8
0x7ffc250920e7 LC_ADDRESS=zh_CN.UTF-8
0x7ffc250920fe XDG_SESSION_ID=c1
0x7ffc25092110 XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/dinosaur
0x7ffc25092144 LC_MONETARY=zh_CN.UTF-8
0x7ffc2509215c CLUTTER_IM_MODULE=xim
...

glibc变量

定义

定义在glibc-master/posix/environ.c

/* This file just defines the `__environ' variable (and alias `environ').  */

#include <unistd.h>
#include <stddef.h>

/* This must be initialized; we cannot have a weak alias into bss. */
char **__environ = NULL;
weak_alias (__environ, environ) // 弱引用 其实environ 就是__environ
...

读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;
}

写 putenv setenv

putenv setenv 都调用__add_to_environ

int
__add_to_environ (const char *name, const char *value, const char *combined,
int replace)
{
const size_t namelen = strlen (name);
size_t vallen;
...
vallen = strlen (value) + 1;
...
const size_t varlen = namelen + 1 + vallen;
...
memcpy (new_value, name, namelen);
new_value[namelen] = '=';
memcpy (&new_value[namelen + 1], value, vallen);
...
}

其实就是char ** environ 变量存着 key=value的字符串

如何以及什么时机继承

// todo 有空扒一下

总结

环境变量是一堆字符串,继承通过进程父子关系

1 环境变量的来源、原理与应用

2 glibc 文档