基本概念
- 环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,他是系统中某些具有全局性质的变量,通常是为了满足某些系统的需求。
- 环境变量=变量名+变量内容(路径);环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。
- 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
查看环境变量方法
可以使用echo命令来查看环境变量,语法格式为:
echo $NAME #NAME为环境变量名
实例演示:
常见环境变量
常见的环境变量有很多,这里我们分析其中最常见的三个:
- PATH:指定命令的搜索路径,即执行命令的时候,在PATH命令中的路径中寻找命令。
- HOME:指定用户的主工作目录。
- SHELL:当前使用的shell版本,通常为/bin/bash
测试PATH
PATH:中存放的环境变量是为了在执行命令的时候,可以在PATH中找到对应的路径,这样就可以不用写出命令绝对路径了。
举一个简单的例子:
ls命令是最常用的命令之一,其实也不过是在系统中的一个封装的可执行程序而已,我们可以使用which命令查看ls的路径,可以看到ls的路径为:
/user/bin/ls #查看当前目录下的文件
但是通常我们是直接使用ls命令的,而我们写的程序,却要加上./,这是为什么?
看下面的图,可以看到,ls这个指令的路径被写进了环境变量PATH中,所以,当我们执行ls这个指令时,系统会在环境变量PATH下挨个搜索路径,找到就执行,找不到就报错
那现在又有一个问题,我们的程序能不能使用同样的方法实现不带路径就可以执行程序囊?
答案是肯定的,下面我们就来看看如何做。
修改PATH的方法
通常我们自己在写完一个代码后,形成了一个可执行文件,需要通过./这样的方式才可以运行,这是因为环境变量PATH中没有当前可执行程序的工作目录,所以我们只能通过./这样的方式,自己手动的通过相对路径的方式运行可执行程序。
如果想让我们的可执行程序可以直接像ls命令那样直接运行,我们可以用两种方法:
1.在PATH创建一个新目录
将当前工作目录添加到PATH中即可。
使用exportt命令,在PATH中添加新的工作目录
export PATH=$PATH:/home/name/test.c/
- 完上述命令的话,就可以直接使用test指令。
注意:这样操作的话,其实在下一次重新开使用linux的时候,原来的环境变量就会被重新覆盖,导致test不能直接被使用。如果想要永久得到命令生效,就需要修改~/.bash_profile才行。
vim ~/.bash_profile #将创建工作目录的指令写在bash_profile中 source .bash_profile #使得bash_profile中的内容生效
环境变量相关指令
- echo:显示某个环境变量值
- export:设置一个新的环境变量
可以将local本地变量变成全局变量
- env:显示所有环境变量
- unset:清除环境变量
- set:显示本地定义的shell和环境变量,和env中的环境变量相比,set中的环境变量只在本进程中有效。
环境变量的组织方式
环境变量的存储方式就是利用的指针数组,一个数组中存放了很多的指针,每一个指针都指向一个环境变量的首地址,因此我们可以找到对应的环境变量,并且指针数组的最后一定存放了NULL做为结尾.
结:每一个进程都会收到一个环境表,环境表本质是一个以NULL为结尾的指针数组。
获取环境变量的三种方式
main()函数第三个参数
上面我们说过,main函数有三个参数,介绍了前两个,那么第三个参数就是env指针数组,就是上面的这张图,里面存在着一个一个的环境变量。
int main(int argc,char* argv[],char* envp[]);
- argc:代表调用main()函数进程的时候,传入的参数个数
- argv:代表调用main()函数进程的时候,传入的参数
- envp:代表环境变量表,由此获取系统的环境变量.
案例一:
#include <iostream> using namespace std; int main(int argc, char* argv[]) { for (int i = 0; i < argc; i ++) { cout << argv[i] << endl; } return 0; }
运行结果:
分析
案例二
#include <iostream> #include <cstring> using namespace std; int main(int argc, char* argv[], char* envp[]) { for (int i = 0; envp[i]; i ++) { cout << envp[i] << endl; } return 0; }
运行结果
第三方变量environ
第二种方法:可以使用第三方变量environ获取。
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。
#include <iostream> using namespace std; int main() { extern char** environ; for (int i = 0; environ[i]; i ++) { cout << environ[i] << endl; } return 0; }
运行结果:
和main()函数第三个参数显示的结果相同
系统调用接口getenv()
直接调用系统接口getenv().getenv函数可以根据所给的环境变量名,在环境变量表中进行搜索,并返回一个找到搜索的环境变量的指针。
#include <iostream> #include <stdlib.h> // getenv()函数在<stdlib.h>的头文件中 using namespace std; int main() { cout << getenv("HOME") << endl; return 0; }
环境变量的全局属性
环境变量通常具有全局属性,父进程的环境变量信息可以被子进程继承下去
代码如下:
#include <iostream> using namespace std; int main(int argc, char *argv[], char *env[]) { cout << getenv("MYENV") << endl; return 0; }
测试结果如下:
直接运行的话,发现没有结果,因为MYENV是一个本地变量,还不是环境变量。
第二次通过父进程bash导出环境变量MYENV,再次运行程序,有结果,这是因为子进程继承了父进程bash的环境变量,所以本次执行程序有结果
总结:环境变量可以被子进程继承下去,因为环境变量通常具有全局属性。