Linux 进程--Environment extern, environ, getenv, setenv
本系列的重点将放在过程环境、过程控制、过程关系等的实际方面。
在本文中,我们将讨论如何在 C 程序中获取和设置环境变量。
什么是过程?
进程可以被认为是正在执行的程序的一个实例。我们称之为“程序实例”,因为如果同一个程序运行 10 次,那么将有 10 个相应的进程。
继续前进,每个进程都有自己唯一的进程 ID,通过它在系统中进行标识。除了它自己的 ID,父进程 ID 也与一个进程相关联。
main() 函数
“C”程序总是以调用 main() 函数开始。这是程序运行时调用的第一个函数。
main() 函数的原型是:
int main(int argc, char *argv[]);
在上面的原型中:
- main() 函数的返回类型是“int”。这是因为,当 main() 函数退出时,程序结束。main() 的返回类型表示程序是否正确执行。严格来说,我们说如果 main() 返回 '0',则程序执行成功。任何其他返回值都表示失败。
- main() 函数接受两个参数。一个是命令行参数的数量,另一个是所有命令行参数的列表。
让我们用一个小示例代码来解释上述要点。
#include<stdio.h>
int main(int argc, char *argv[])
{
int count = argc;
printf("\n The number of arguments passed is [%d] \n", count);
int c = 0;
while(c < count)
{
printf("\n The argument [%d] is : [%s]\n", c+1, argv[c]);
c++;
}
return 0;
}
上面的 C 代码打印传递给它的命令行参数的数量,并打印每个参数的值。
当程序执行时,它会显示以下输出:
$ ./main abc 1 3
The number of arguments passed is [4]
The argument [1] is : [./main]
The argument [2] is : [abc]
The argument [3] is : [1]
The argument [4] is : [3]
我们向程序“main”传递了 3 个参数,但日志通知它收到了 4 个参数。这是因为程序的名称(我们用来执行它)也被视为命令行参数。
此外,由于上述程序是在终端上运行的,因此 main() 函数的返回值也会发送给它。你可以使用bash shell 的特殊参数$? 如下图检查返回值(0表示成功)。
$ echo $?
0
- 回到 main 函数,当内核执行 C 程序时,会使用“exec”函数来触发程序。
- 然后在下一步中,在程序的 main() 函数之前调用一个典型的启动例程。
- 同样,当程序结束执行时,也会调用一个典型的结束例程。
- 如果我们查看任何可执行文件,我们会发现它指定了启动例程和 ens 例程地址作为第一个例程和最后一个要调用的例程。
- 启动例程从内核获取命令行参数、环境等,并将它们传递给 main() 函数。
- 包括启动和结束例程的整个设置由链接器在编译过程的链接阶段完成。
环境清单
在 Linux 提示符下键入命令“env”,您将获得名称=值对的列表。这代表您的 shell 环境。同样,一个进程也有它的环境。我们可以通过两种方式访问进程环境:
- 通过全局变量' extern char **extern '
- 通过 main() 函数的第三个参数 'char *envp[]'
关于 envp[](第三个参数),您可能会问 main() 函数的第三个参数从何而来,正如我们之前讨论的 main() 函数只有两个参数。
嗯,历史上存在 main() 函数的第三个参数(环境数组)。但是 ISO C 规定 main() 函数只用两个参数编写。因此,当我们指定 main 函数时,我们不使用这第三个参数。但是,我们可以在程序中访问这个 envp[]。
无论如何,回到环境列表,以下代码片段指定了如何从进程中访问环境:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
extern char **environ;
int main(int argc, char *argv[])
{
int count = 0;
printf("\n");
while(environ[count] != NULL)
{
printf("[%s] :: ", environ[count]);
count++;
}
char *val = getenv("USER");
printf("\n\nCurrent value of environment variable USER is [%s]\n",val);
if(setenv("USER","Arora",1))
{
printf("\n setenv() failed\n");
return 1;
}
printf("\n Successfully Added a new value to existing environment variable USER\n");
val = getenv("USER");
printf("\nNew value of environment variable USER is [%s]\n",val);
while(1)
{
sleep(2);
}
return 0;
}
在上面的代码中,我们使用了全局变量 'environ' 来访问所有的环境变量。我们还使用了两个功能:
- getenv – 获取特定环境变量的值
- setenv – 为环境变量设置一个新值
上述程序的输出结果是:
$ ./environ
[ORBIT_SOCKETDIR=/tmp/orbit-himanshu] :: [SSH_AGENT_PID=1627] :: [TERM=xterm] ::
[SHELL=/bin/bash] :: [WINDOWID=39846040] :: [GTK_MODULES=canberra-gtk-module] ::
[USER=himanshu] :: [SSH_AUTH_SOCK=/tmp/keyring-6kpqGc/ssh] ::
..
..
Current value of environment variable USER is [himanshu]
Successfully Added a new value to existing environment variable USER
New value of environment variable USER is [Arora]
上面的输出将整个环境列表打印到标准输出。上面的代码片段还使用 getenv 和 setenv 来获取 USER 环境变量并更改其值。
- 点赞
- 收藏
- 关注作者
评论(0)