樊梓慕:个人主页
个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C++》《Linux》
每一个不曾起舞的日子,都是对生命的辜负
目录
前言
1.环境变量是什么?
1.1查看环境变量的方法
1.2常见的环境变量
1.2.1PATH
1.2.2USER
1.2.3PWD
1.2.4HOME
2.环境变量的特性
2.1补充知识:命令行参数
2.1.1int argc与char* argv[]
2.1.2char* env[]
2.2环境变量如何具有全局属性?
3.环境变量的代码获取和设置
3.1代码获取环境变量
3.1.1通过main函数的第三个参数获取环境变量(不常用)
3.1.2通过getenv()函数获取环境变量(常用)
3.1.3通过第三方变量environ获取环境变量(不常用)
3.2设置环境变量
3.3本地变量的设置与查看
3.4unset取消环境变量或本地变量
4.环境变量的配置文件
本篇文章博主将会与大家共同学习环境变量,那么环境变量究竟在扮演着什么样的角色呢?
为什么我们在编写C/C++代码时,不需要显式的告诉编译器我们所需要链接的动态静态库在哪,但链接照样可以成功并生成可执行程序,其实这里就是有环境变量的辅助。
欢迎大家收藏以便未来做题时可以快速找到思路,巧妙的方法可以事半功倍。
=========================================================================
GITEE相关代码:fanfei_c的仓库
=========================================================================
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
下面带你认识几种环境变量来辅助你理解环境变量。
实例:echo $NAME //NAME:你的环境变量名称
实例:env //显示所有环境变量
如何执行一个可执行程序?
可是为什么系统自带的命令(本质就是可执行程序)不需要带文件路径呢?
比如:
其实就是环境变量PATH的配置,我们查看一些PATH的内容:
我们发现pwd的路径就在PATH中,也就是说,可执行程序的路径如果在环境变量PATH中,那么就可以不需要带文件路径的执行了。
我们来试试:
你当然可以将你的可执行程序放到环境变量中的路径下,但是我并不推荐你这样做,因为你会污染你的系统目录,从而引发一些不必要的麻烦。
所以你可以这样做:修改环境变量。
注意:如果你不慎覆盖了PATH,可以直接关闭XSHELL,因为你覆盖的PATH是加载到内存中的,重启XSHELL会重新读取磁盘中的文件,重新初始化PATH。
当我们执行whoami时,系统是如何知道当前用户是谁的,是因为有USER这个环境变量。
当我们执行pwd时,系统是如何知道当前路径的,是因为有PWD这个环境变量。
当我们访问家目录时,系统是如何知道家目录在哪的,是因为有HOME这个环境变量。
好了,举这些例子都是为了解释说明环境变量的概念。
定义变量的本质其实是开辟空间,所以系统的环境变量本质就是系统或bash开辟的一块内存空间,存放着名称和数据。
环境变量通常具有全局属性,可是为什么呢?
其实是因为环境变量会被子进程继承下去,所以环境变量才具有全局属性。
那么我们就来探究下这个继承的过程,但在开始前我们需要一点补充知识。
main函数有参数么?
之前学习C/C++时,我从未见过main函数有参数。
但实际上main函数拥有三个参数:
那我们来打印一下试试,这两个形参是什么内容:
我们发现打印出来的好像是我们输入的命令啊。
所以我们来推测一下命令行解释器bash会干什么:
那我们再来写一段代码:
int main(int argc, char* argv[], char* env[])
{
if (argc != 4)
{
printf("Usage:\n\t%s -[add|sub|mul|div] x y\n\n", argv[0]);
return 1;
}
int x = atoi(argv[2]);
int y = atoi(argv[3]);
if (strcmp("-add", argv[1]) == 0)
{
printf("%d+%d=%d\n", x, y, x + y);
}
else if (strcmp("-sub", argv[1]) == 0)
{
printf("%d-%d=%d\n", x, y, x - y);
}
else if (strcmp("-mul", argv[1]) == 0)
{
printf("%d*%d=%d\n", x, y, x * y);
}
else
{
printf("unknown!\n");
}
return 0;
}
也就是说这两个参数就可以让我们通过不同的选项,使同一个程序执行它内部不同的功能。
这是不是就是我们平时使用的指令后面跟上不同的选项,执行内部不同的功能!?
命令行参数也是Linux指令选项的基础。
同样的我们来打印看看该参数传递了什么?
int main(int argc, char* argv[], char* env[])
{
printf("I am a process, pid: %d, ppid: %d\n", getpid(), getppid());
for (int i = 0; env[i]; i++)
{
printf("env[%d] -> %s\n", i, env[i]);
}
return 0;
}
也就是说main函数的第三个参数传递的是环境变量!
上面介绍main函数的第三个参数char* env[]时,我们发现他传递的是环境变量,也就是说环境变量具有全局属性的方法就是通过子进程继承父进程的环境变量,而其传递所用的方式就是该参数。
比如:bash在创建子进程时会维护两张表,一张表为命令行参数字符串数组,另一张表为环境变量字符串数组,bash作为父进程会将这两张表传递给子进程,子进程通过main函数的第三个参数进行接收。
首先第一种通过代码获取环境变量的方式就是利用main函数的第三个参数,前面已经讲过了,这里就不多赘述了。
int main()
{
const char* username = getenv("USER");
printf("username: %s\n", username);
return 0;
}
识别用户:
int main()
{
const char* username = getenv("USER");
if (strcmp(username, "ff") == 0 || strcmp(username, "fanzimu") == 0)
{
printf("this is my process core function\n");
}
else
{
printf("你没有权限\n");
}
return 0;
}
首先我们通过man指令来查看下environ
environ是指向环境变量字符串数组的二级指针。
所以我们可以通过该二级指针获取环境变量。
代码如下:
#include
int main(int argc, char* argv[])
{
extern char** environ;
int i = 0;
for (; environ[i]; i++) {
printf("%s\n", environ[i]);
}
return 0;
}
实例:export AGE=22
相当于给bash导出的环境变量,当执行myprocess后,bash是myprocess的父进程,所以myprocess继承了父进程的环境变量,所以该环境变量也就具有了全局属性。
注意:本地变量无法再env表中查到,且本地变量不会被子进程继承,不全局,只在bash中有效。
set命令:显示本地定义的变量和环境变量。
实例:unset [变量名]
我们之前说环境变量是内存中的数据,我们每次在bash上修改环境变量,下次重登录的时候,所有环境变量会初始化,之前修改的内容就会被重新覆盖成最开始的内容,那很明显,这是因为环境变量是从磁盘中的某个文件中读取而来的。
环境变量的配置文件:.bash_profile
该配置文件在每个用户的家目录下。
如果我们对其内容进行修改:
下次重登录时,我们发现修改的环境变量被读取了:
讲完环境变量,你是否可以理解为什么我们每次登录默认所在的路径就是你自己的家目录呢?
那是因为每次登陆最开始系统需要读取你自己的环境变量配置文件!
=========================================================================
如果你对该系列文章有兴趣的话,欢迎持续关注博主动态,博主会持续输出优质内容
博主很需要大家的支持,你的支持是我创作的不竭动力
~ 点赞收藏+关注 ~
=========================================================================