一.概念
环境变量(environmentvariables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数。
注意,使用环境变量的是bash。
当然,对于小白来说没办法理解,接下来将带大家将逐步拆解,并举几个例子,帮助大家理解环境变量。
1.argv与命令行参数(理解命令选项的实现)
main函数有形参吗?答案是有的,分别是argc和argv。这里以一个实验,辅助我们理解这两个参数以及命令行参数:

命令行是一个字符串,而bash 能够将命令行里的字符,以每一个空格作为一次切割,将每一次切割下来的子串放入argv的一个元素 中。而agrc就是argv中有效元素的个数。

那么命令行参数是谁呢?就是a,b,c,d,即跟在命令后面,在程序运行时,在命令行传给程序的参数。所以argv里装的就是命令和命令行参数。
那么设计命令行参数有何用呢?再根据一个实验来进行说明:

可以根据输入不同的命令行参数,来选择函数的子功能 。关于-a,-b大家是否眼熟呢?没错,这就是通过不同选项,实现程序(命令)不同子功能的底层逻辑。
2.理解环境变量------path
首先我们得先弄明白一个问题,为什么执行系统命令这个程序时无需带上"./",而自己编写的程序需要带上?
答案是,要执行一个程序,需要先找到它 ,而系统内部存在环境变量,可以辅助系统找到目标程序的二进制文件。所以系统命令不需要带./。
那么把自己写的程序的二进制文件拷贝到系统目录usr/bin/下,是不是也可以借助环境变量,进而不需要带./了呢?是这样的,我们实操一遍验证一下:

再来探讨一下,系统内部帮助寻找二进制文件的环境变量:
它叫做PATH ,能够提供默认搜索路径。
环境变量 = 名称 + 内容。
可以用指令echo + $path看到这些默认搜索路径(PATH的内容),每个路径是用":"隔开的:
当输入一个命令后,操作系统会到PATH的这些路径下,挨个路径查找这个命令,所有路径都遍历一次之后,还是找不到的话,就会报找不到目标文件的错误。
既然PATH是提供默认路径给系统的,那我把自己写的程序的路径粘贴到PATH下,是不是也可以执行程序时,不用带上./了,答案是正确的,那么该如何粘贴呢?
直接输入PATH = 路径就可以了。

但这么做是有恶果的,因为PATH下的所有默认路径全部被该路径覆盖了,当执行其他命令的时候,系统就找不到对应的二进制文件了:

那么有没有既能粘贴路径,也不会覆盖之前默认路径的方法呢?
有的兄弟,有的:

3.环境变量们储存在何处?
登陆的时候,系统会为每个登录的用户创建一个bash进程,bash从系统读取环境变量信息,进而z在bash内部形成一张环境变量表。这是一个指针数组,每个元素存储一个字符串指针,每个指针指向一个路径字符串。因而环境变量储存在bash的环境变量表中。

所以bash内部有两张表,一张命令行参数表(argv),一张环境变量表(env)。
4.环境变量最开始从哪来?
那么bash获取的环境变量的信息是从哪来的呢?答案是从系统的相关配置文件中来!
5.环境变量------HOME
当登录成功以后,将用户的路径默认设置为**/home/用户名,** 然后HOME记录当前用户的家目录。

bash会从环境表里拿到HOME,进而得到当前用户家目录。
6.设置新环境变量的方法
export+环境变量名=环境变量内容

7.环境变量相关的命令

注意:echo+$环境变量名才可以查看具体环境变量的内容!
8.再探main函数形参
main函数还有一个形参------环境变量表char*env\[\],对,就是bash的第二张表。bash会把两张表作为参数传给main函数。
那为什么main函数可以传不固定数量的参数呢?
答案是程序在执行时,并不是从main函数开始的,而是从_start函数开始,它会去调用main函数,_start内部会定义一个变量arg_count,去统计它将要调用的main函数的形参数量,根据不同的数量去调用不同实参个数的main函数:

既然main函数的形参里有环境变量表,就说明它可以获取父进程bash的环境变量,换句话说,环境变量可以被子进程继承,甚至孙子,曾孙进程继承,所以说环境变量在在系统中具有全局特性。至于父进程怎么把环境变量交给main函数,那是后话了。
那为什么要设计这种继承家业的模式呢?
答案是子进程可以根据这些继承来的环境变量,进行个性化的操作:
就比如用环境变量USER搓一个我能执行,而其余用户都没法执行的程序出来:

9.总结之获取环境变量内容的方法
1."继承家业",即env\[\]作为形参,然后可以把整个env\[\]打印出来。
2.用函数getenv,加指定环境变量名。获取指定环境变量的内容。(推荐)

10.概念补充------本地变量与内建命令

export命令如果跟寻常命令一样,在执行时,需要bash创建子进程来执行的话,那么子进程导入新环境变量,给bash这个父进程,就倒反天罡了,只能子进程继承父进程环境变量!这就说明,**export命令在执行时,是不需要创建子进程的,而是让bash来亲自执行!export是个内建命令(built-in command)。当然,cd,pwd也是内建命令。**就像吕芳不可能把所有事情都放给自己的干儿子们去做,他自己还是得攥着一两件,去自操刀的。

