C语言标准库函数getenv的实现

C语言标准库函数getenv可获取环境参数(根据参数名称),
函数声明:char* getenv(char*name);


其实现如下:


---------------glibc-1.09.1/sysdeps/generic/getenv.c
/* Return the value of the environment variable NAME.  */
char *
DEFUN(getenv, (name), register CONST char *name)
{
  register CONST size_t len = strlen(name);
  register char **ep;


  if (__environ == NULL)
    return NULL;


  for (ep = __environ; *ep != NULL; ++ep)
    if (!strncmp(*ep, name, len) && (*ep)[len] == '=')
      return &(*ep)[len + 1];


  return NULL;
}




其中全局指针__environ指向环境参数串的指针数组,通过循环匹配找到指定的参数名称,获取=后的参数值并返回其指针。
那么__environ是在哪定义的呢?是在start.c中。


---------------glibc-1.09.1/sysdeps/unix/start.c
C程序链接时,这部分stub代码会链接到在程序开始处,_start是C程序真正的入口,_start调用start1,
而start1在调用初始化代码__libc_init后会调用main()。
从下面的代码看出,为什么main中末尾无需exit(),因为start1代劳了。至于堆栈中的argc,argv,envp
这些都是操作系统在调用系统调用execve执行程序时就安排好的,start1的形参可以去到这些进程参数和环境变量,
全局指针environ则等于envp(指向环境参数指针数组的指针)。


…………
#define	__environ	environ
…………
static void start1();
…………
/* N.B.: It is important that this be the first function.
   This file is the first thing in the text section.  */
void
DEFUN_VOID(_start)
{
  start1();
}
…………
/* ARGSUSED */
static void
start1(ARG_DUMMIES argc, argp)
     DECL_DUMMIES
     int argc;
     char *argp;
{
  char **argv = &argp;


  /* The environment starts just after ARGV.  */
  __environ = &argv[argc + 1];


  /* If the first thing after ARGV is the arguments
     themselves, there is no environment.  */
  if ((char *) __environ == *argv)
    /* The environment is empty.  Make __environ
       point at ARGV[ARGC], which is NULL.  */
    --__environ;


  /* Do C library initializations.  */
  __libc_init (argc, argv, __environ);


  /* Call the user program.  */
  exit(main(argc, argv, __environ));
}

正常的内存堆栈布局是这样的

地址从低到高:
int argc 
char** argv(指针数组,0结尾)
char** envp(指针数组,0结尾)
string[] arg(顺序排列的参数串数组,每个参数串0结尾) 
string[] env(顺序排列的环境参数串数组,每个参数串0结尾) 
其中argv[0]指向arg[0],argv[1]指向arg[1],……。
正常情况 &argv[argc+1]=envp,但是如果环境参数没有,那么堆栈中就没有envp指针数组和env串数组,那么argv后就直接是
arg的参数串数组了,此时堆栈布局如下:
int argc 
char** argv(指针数组,0结尾)
string[] arg(顺序排列的参数串数组,每个参数串0结尾) 


所以有&argv[argc+1]=*argv (第一个参数指针argv[0]是指向第一个参数串的),这是上述代码中
if ((char *) __environ == *argv)
    /* The environment is empty.  Make __environ
       point at ARGV[ARGC], which is NULL.  */
    --__environ;

的由来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值