linux环境变量

来源:互联网 发布:农村淘宝服务站点查询 编辑:程序博客网 时间:2024/06/10 17:46

一 环境变量的作用

使用环境变量的好处是:不用重新编译源程序即可通过环境变量可以改变程序的行为。


二 实现原理

char **__environ = 0;
weak_alias(__environ, environ)
__environ 是libc中定义的char **类型指针变量,初始化过程:
__uClibc_main()
{
...........
/* The environment begins right after argv.  */
    __environ = &argv[argc + 1];
..........
result = main (argc, argv, __environ);
}
应用添加环境变量通过setenv()函数:
int setenv(const char *name, const char *value, int replace)
{
/* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */
return __add_to_environ(name, value ? value : "", replace);
}
static int __add_to_environ(const char *name, const char *value,
  int replace)
{
ep = __environ;

size = 0;
if (ep != NULL) {
while (*ep != NULL) {
if (!strncmp(*ep, name, namelen) && (*ep)[namelen] == '=') {
/* Found */
if (!replace)
goto DONE_OK;
goto REPLACE;
}
++size;
++ep;
}
}
/* Not found, add at the end */


/* We allocated this space; we can extend it.  */
new_environ = realloc(last_environ, (size + 2) * sizeof(char *));
if (new_environ == NULL) {
__set_errno(ENOMEM);
goto DONE;
}
if (__environ != last_environ) {
memcpy(new_environ, __environ, size * sizeof(char *));
}
last_environ = __environ = new_environ;


ep = &new_environ[size];
/* Ensure env is NULL terminated in case malloc below fails */
ep[0] = NULL;
ep[1] = NULL;
 
REPLACE:
var_val = (char*) name;
/* Build VAR=VAL if we called by setenv, not putenv.  */
if (value != NULL) {
const size_t vallen = strlen(value) + 1;


var_val = malloc(namelen + 1 + vallen);
if (var_val == NULL) {
__set_errno(ENOMEM);
goto DONE;
}
memcpy(var_val, name, namelen);
var_val[namelen] = '=';
memcpy(&var_val[namelen + 1], value, vallen);
}
*ep = var_val;
...........
}
通过代码很容易理解,后来添加的环境变量是存放在堆上的。
调用clearenv()清除所有的环境变量,包括栈上的
int clearenv(void)
{
__UCLIBC_MUTEX_LOCK(mylock);
/* If we allocated this environment we can free it.
* If we did not allocate this environment, it's NULL already
* and is safe to free().  */
free(last_environ);
last_environ = NULL;
/* Clearing environ removes the whole environment.  */
__environ = NULL;
__UCLIBC_MUTEX_UNLOCK(mylock);
return 0;
}
关于环境变量的继承也很简单,看看execv()函数的实现:
int execv(__const char *path, char *__const argv[])
{
return execve(path, argv, __environ);
}
通过将所有环境变量拷贝到栈上,由父进程向子进程传递。
原创粉丝点击