今天看了一个linux环境变量使用的例子,代码如下:
#include
#include
extern char **environ;
int main()
{
char**var;
for(var=environ; *var != NULL; ++var)
printf("%s \n", *var);
return 0;
}
得出的结果是什么呢?如下所示:
TERM=xterm-color
SHELL=/bin/bash
XDG_SESSION_COOKIE=6af527ad059c531fe242b1f04b0a6705-1278913245.558340-1417734209
SSH_CLIENT=192.168.12.165 1761 22
SSH_TTY=/dev/pts/3
......
也就是说,environ变量中存放的是 "key=value" 这种键值对格式的列表。
那么 environ 这个外部变量是什么时候存入值的呢?这是个很值得追究的问题,知其然还要知其所以然吗。
经过多方查找,我在 赵炯 博士的著作《linux内核完全注释》电子版中的第631~633中找到了答案。
我们在写 C 程序时 , 一般的写法如下:
int main(int argc, char *argv[])
其实,在 main 入口处还可以有另外一个参数 char *envp[]。即
int main(int argc, char *argv[], char *envp[])
其中 envp[] 数组中存放的就是 "key=value" 这种键值对。只不过 envp 这参数不能由我们自己控制,而是由linux系统设置的。
那么linux中 envp 与 environ 之间是如何联系在一起的呢?
这个就有意思了,在linux内核中有一个crt0.S 的桩代码,它会与所有执行程序编译后链接在一起。当加载器加载程序时,首先就会执行这个桩代码。它长的什么样子呢?如下图所示:
在上面的桩代码中,将 envp 的地址赋值给了_environ 全局变量。这样他们就联系起来了,我们也就可以在 C 语言中直接使用environ进行环境变量的访问了。
虽然现在我们知道了environ是什么时候被赋值的,但还是不清楚它的值来自于那。还是让我们再次深入到内核中去看看吧。
我们的程序在执行时,是通过 shell 执行的。shell会调用 fork() 函数分配一个子进程,子进程会调用 exec 族函数之一加载执行新程序。exec函数的主要功能如下:
也就是说,exec函数在加载程序时,设置了 envp 的值,并在调用上面的桩代码时将 evnp 的地址赋值给了 environ 变量。这一下我们就全明白了,呵呵。
下面我们来进行收尾工作,再来看一下内存中是如何存放参数和环境变量的。如下图:
这个图已经画的很清楚了,我就不在啰嗦了,希望这篇文章能对大家有所帮助。:)
~
阅读(1335) | 评论(0) | 转发(0) |