环境变量
- 1.环境变量
- 1.1 概念引入
- 1.2 PATH 环境变量
- 1.2.1 读取环境变量内容 :echo
- 1.2.1 设置环境变量: export
- 1.3 USER 环境变量
- 2.环境变量的组织形式(表)
- 2.1 env 命令查看所有的环境变量
- 2.2 用代码的方式查看环境变量
- 2.2.1 利用 char* envp[ ] 参数查看环境变量
- 2.2.2 利用全局变量查看环境变量
- 2.2.3 调用函数的方式去查看环境变量
- 3. shell 中的变量
- 4. main函数参数的作用
1.环境变量
1.1 概念引入
- 环境变量:一般是指在操作系统中用来指定操作系统运行环境的一些参数,并且在系统当中通常具有全局特性
一般概念都是总结性的,在讲环境变量前来想这样一个问题:
为什么自己编写的可执行文件在命令行运行时要以 ./
(./
表示当前目录下) 才能将这个程序跑起来?
命令也是程序,为啥输入命令的时候就不用带 ./
?例如:ls、cd、pwd…
这就关乎到一个环境变量:PATH
1.2 PATH 环境变量
- PATH环境变量:主要用于存储一系列由冒号分隔的目录路径,在这些目录路径中存放着可执行文件。当用户在命令行中尝试运行一个程序时,操作系统会在这些目录中查找相应的可执行文件。
在Linux下,将可执行文件放在这些目录下,执行时可以不用带上 ./
,就像命令式那般使用。
1.2.1 读取环境变量内容 :echo
echo
:是用于查看变量或者在终端打印字符串的命令
如果我们直接使用 echo 命令的话会出现以下情况:
在查看环境变量时需要带上 $
符号:
$
:像是C语言的指针的作用,带上$
符号可以将变量内容打印出来
下面是正确查看 PATH环境变量内容的方法:
我们将自己编写的可执行文件的文件目录设置在PATH环境变量里,就可以实现像命令式使用我们自己的可执行文件。
简单编写一个可执行文件:
正常的运行该文件是需要带上 ./
的:
下面我们将这个可执行文件的路径添加到 PATH 环境变量里。
1.2.1 设置环境变量: export
语法:export 环境变量名=添加的内容
export PATH=$PATH:目录路径
下面将当前目录的路径添加到 PATH环境变量内容中:
下面再将刚刚编写的可执行文件不带 ./
进行运行:
切记不要在添加路径时将 PATH 环境变量写成如下情况:
export PATH=目录路径
运行自己的可执行文件是没有问题,但是
上述操作会造成 PATH 环境变量的原有目录路径都被替换成新目录的路径,想要恢复的话只能退出当前用户重新登录
因此 PATH 环境变量的作用是:当用户要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还会到PATH环境变量中指定的路径去找。通过正确设置PATH环境变量,用户可以更方便地运行程序,而不必每次都输入完整的程序路径
当然系统中不仅仅只有一个 PATH 环境变量,还存在很多不同功能的环境变量。
例如:USER环境变量
1.3 USER 环境变量
当一个用户登录时,USER环境变量就会记录下当前机器登录的用户。
不同用户登录Linux时,USER环境变量指向的内容都会不一样。
下面以root身份进行登录,再来查看 USER环境变量:
在Linux中,创建的文件都是有不同属性和权限。操作系统为了区分哪些文件可以被哪些用户进行读写,就是通过USER环境变量来控制的。
2.环境变量的组织形式(表)
- 诸多的环境变量组织起来就变成了一张表,叫做 环境变量表。它是一个内存级别的一张表,每当在用户登录操作系统时,都会创建一张属于当前用户的环境变量表
内存级别表示:这张表不是在磁盘中进行维护,当用户登录操作系统时,环境变量表会在内存中创建。当用户退出登录或是重新登录时,这张表就会被重新刷新初始化。
环境变量对应的数据存储在系统对应的配置文件中,配置文件的位置在当前用户家目录下:
用vim打开
可以看.bash_profile 和 .bashrc 这两个文件其实就是两个 shell 脚本,当用户登录成功后就会按照这些配置文件对环境变量进行配置。进而形成一张内存级别的表
这个表是一个字符指针数组,数组种的每个元素都是指向一个以 \0 结尾的环境字符串
环境变量表实际上是指每个进程所持有的环境变量集合的抽象表示(记住这句话,后面会提到)。表中的每个条目都是形如key--val
的键值对。
下面来查看一下环境变量表长什么样:
2.1 env 命令查看所有的环境变量
在Linux中 shell 是一个命令行解释器,它是一个进程,对应的它有属于他的一张环境变量表。
在终端输入命令 :env
可以查看对应的环境变量表
env
输出的内容很多,但是可以看到几个熟悉的字眼,例如:USER、PATH、HOME。
可以看到一些规律,每一个条目中都有 大写字母 = 环境变量对应的内容,就是上面所说的键值对。
每一个大写字母单词代表就是一个环境变量,等号右边就是对应环境变量的有用的信息
除了用命令方式查看,也可以利用代码的方式来查看环境变量表。
2.2 用代码的方式查看环境变量
开始前,重新认识一下 main 函数:
main 函数是我们自己写的代码运行时的入口,这个是基于我们平时的认知。
但从现在开始就要用另一种方式去看待 main函数。
main 函数是一个函数,是一个函数那么就可以被传参,是函数就是可以被调用。
那么问题来了 main 函数是被谁调用的呢?当然是 bash !为什么这么说?
在命令行中运行一个程序的过程就是创建进程,使用./
操作其实就是 shell 调用这个程序的 main 函数的过程。
在调用 main 函数时,shell 会将环境变量表传给main函数。
你没有看错,在main函数中是可以传参的。main函数不仅可以传参,而且参数有三个之多。
main 函数中可以传入三个参数分别是:
int argc
、char* argv[ ]
、char* envp[ ]
提示:这里先介绍main函数的最后一个参数 envp ,该篇博客后续内容会介绍前面两个参数的作用。
参数 char* envp[]
作用是用来接收环境变量表的
2.2.1 利用 char* envp[ ] 参数查看环境变量
- main 函数的第三个参数的类型为:字符指针数组,数组内的每一个指针都是指向对应的不同的环境变量的地址
前面提到过:环境变量表实质上就是一个字符指针数组,在这里有所不同的是数组的最后一个元素为NULL。
因此我们可以用代码的方式将环境变量输出:
字符指针数组中的最后一个元素为空,那么就可以将 NULL值设置为结束的条件,下面看看运行结果:
数组中的每一个元素都是一个字符指针,打印结果就是一个环境变量字符串。
查看环境变量的方法还有两种,接着往下看:
2.2.2 利用全局变量查看环境变量
在C语言中有那么一个全局变量也可以用来查看环境变量:
char** environ;
它是一个二级指针,可以存储一个char* 类型的地址,前面说到环境变量本质就是一张表,表中存储的是不同环境变量的字符串首元素地址,而这个全局变量就是指向环境变量表的首地址。通过这个全局变量就可以将环境变量表中的元素都打印出来。
使用这个全局变量时需要包含一个头文件:#include <unistd.h>
,当然也需要进行 extern
声明一下,毕竟是在库中。
打印结果如下:
上面两个方法,不是使用参数,就是使用全局变量,很麻烦。有没有一种便捷方式去访问呢?
当然有,下面是第三种方式:
2.2.3 调用函数的方式去查看环境变量
这个函数为:
char* getenv(const char* name);
使用这个函数前也是需要包含头文件的,这个头文件为:#include <stdlib.h>
将需要用到的环境变量名称传递给 getenv
函数,该函数拿到参数后就会在环境变量表中依次对比。
如果查到对应的环境变量存在,会返回对应环境变量的首元素地址;否则会返回NULL。
通过函数调用环境变量是最常用的方式,按照用户的需求去调用需要用到的环境变量。
到这里环境变量是什么?有什么用?怎么调用?都解决了。
但是还有一个问题没有解决,那就是为什么说环境变量表在每个进程中都持有?
3. shell 中的变量
在讲 main 的时候提到过,是 shell 将环境变量表传递给main函数的。
shell 是命令行解释器,可以说 shell 本身就是程序,在Linux中的任何操作都绕不过它。命令也是程序,例如命令:ls、pwd、cat、mkdir… 。使用这些命令的时候,对应都是在 shell 进程中创建子进程的过程。
是程序就是可以创建变量,在 shell 中可以创建属于自己命名的内部变量甚至是环境变量。
举个例子,创建一个简单的变量:
注意:查看变量内容时加上$
符号
在 shell 中创建环境变量,在创建普通变量方法上再加上 export
命令就能将这个变量变成环境变量:
再来查看一下环境变量表:
讲环境变量表的时候说过,环境变量这个表就是一张内存级别的表。当用户登录时OS会按照对应的配置文件内容,在shell中创建属于这个用户的环境变量表。
我们往 shell 创建普通变量时,这个过程就好比在shell内部中 malloc 一段字符空间,然后去存储这个变量的内容。
往shell 创建一个环境变量,这个操作就是在shell中创建普通变量的过程上,再向 shell 中的环境变量表再添加一个字符指针,让表中的指针的去指向这个变量的内容。
在 shell 中执行命令或是可执行文件时,即是在shell 中创建子进程,shell 会把环境变量表传递给子进程,这也是为什么 main函数的参数可以访问到环境变量的原因。
4. main函数参数的作用
调用环境变量说过 main 函数的 char* envp[ ]
参数的作用,这里主要来介绍 main 函数的另外两个参数的作用。
main 函数前两个参数如下:
int main(int argc, char* argv[]);
char* argv[]
是一个字符指针数组,第一个元素是当前程序的名称,其他元素用于存储传递给程序的命令行参数int argc
表示传递给main函数的命令行参数的数量,argc 的值至少为1,表示程序的名称
往 shell 输入命令时,首先是命令的名称,如果要让命令实现不同功能就加上不同的选项。
将命令和命令选项输入到 shell 命令行解释器,shell 会将当前命令进行统计分析。
例如在shell中输入:ls -a -l
shell 会将 ls 命令名称的信息存储到 argv[0];而 -a、-l 选项会依次存储放到字符指针数组的 argv[1]、 argv[2]位置。
再将命令的名称、命令选项个数一个个相加起来,再存储到 argc 变量中。
shell 通过传参的方式将 argc 和 argv 传到当前程序的 main 函数中。main 函数通过这两个参数再利用条件语句,去判断用户输入了哪些命令选项,从而实现不同的功能。
下面来看看实操:
- 运行程序,分别打印出带选项存在 argv 数组中的储位置:
- 实现输入不同选项,让程序表现不同的功能
Linux 环境变量就讲到这里,感谢大家观看!