环境变量
当我们使用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.
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 有空扒一下
总结
环境变量是一堆字符串,继承通过进程父子关系
2 glibc 文档