一、环境变量
1.1 PATH的引入
问题1:为什么我们平时输入的指令可以直接运行,但是自己编译出来的程序却要加 ./?
——>因为指令所需要的相关程序是存储在系统能够查找得到的底下,而我们自己编译出来的程序是在当前的工作目录的,系统并不能直接找到。
问题2:凭什么系统可以找到指令的程序却找不到自己的程序呢??
——> 因为环境变量PATH,他是Linux系统指令搜索路径,用echo $PATH(需要加)可查看系统能够找到的路径 ,其中路径以 “ :”为分隔符 (比如pwd能直接使用就是因为/usr/bin路径在PATH变量中)
如果我们用自己编译的程序,就会显示command not found ,意思就是xshell帮我们找过了,只是他找不到而已
问题3:如果我想让自己写的程序像指令一样去使用,有什么办法呢???
——>(1)思路1:比如/usr/bin路径在PATH变量里,那我们就把自己写的程序放到该路径下即可
(2)思路2:我当前的程序无法使用时因为我的工作目录不在系统的指令搜索路径内,所以我们把当前的工作目录加入到PATH中就行了!!
问题4:如何修改环境变量
——> (1)PATH=…… 但是这样的意思是赋值,也就是说原先的内容会被覆盖掉,这样会导致我们绝大多数指令跑不了(有一部分指令是内建命令,不会被影响) 但是我们只要重新启动xsell就会恢复,因为我们的PATH是一个内存级文件,他是在我们xshell打开之后加载进去的!!
(2)PATH=$PATH:…… 这样的意思就是在原有路径的基础上新增路径
1.2 HOME和SHELL
HOME会在我们xshell登录的时候自动识别用户,然后将根目录载入进去
SHELL 里面的是我们当前的xshell所使用的可执行程序
1.3 查看所有环境变量的方法
1.3.1 命令行形式
env——>查看所有的环境变量
1.3.2 系统调用接口
getenv()
1.3.3 第三方变量获取
extern char **environ
1.3.4 如何通过系统调用接口来判断权限
通过getenv我们可以知道,只要我们将我们想要查找的环境变量放在参数里,就可以以字符串的形式返回 , 所以我们可以用strcmp()这个字符串比较函数,我们的 USER和root一样,那么就是超级用户,其他情况就是普通用户。
所以因为有了环境变量,系统就可以知道你是谁,就可以和文件的拥有者、所属组、其他人的权限进行比较,就可以知道你是否具备对应的权限!!
1.4 命令行参数
1.4.1 选项的两个参数
其实我们的main函数是可以带参数的,因为他其实也是被别人调用的一个函数
int argc:向量表中命令行参数的个数
char* argv[ ]: 其实是一个向量表,里面存储着命令行参数 (最后的位置为nullptr)
我们可以看到向量表的第一个位置一定是这个指令,而后面的位置存放一些附加的选项
这样做的原因是为指令、工具、软件等提供命令行选项的支持,几乎所有的语言都需要命令行参数,因为这样能够为我们的一些选项定制特殊化的功能
1.4.2 系统调用接口模拟实现定制化选项
先暂时不考虑多个选项的情况,因为这个会涉及到可变参数的知识 ,所以我们先假设只能携带一个选项,而由于向量表的第一个位置必然是./mycode 因此第二个位置就是我们携带的选项,因为选项是字符串的形式,因此我们就可以通过strcmp函数通过条件编译,来实现不同的选项实现不同的功能!!
所以另一方面我们可以知道,main函数是如何知道自己有多少个参数呢??其实本质上来说就是main函数也是被别人调用的,所以他在调用的时候就会在底层进行相关的条件编译(也就是对你的参数做检查),不同的参数就走不同的方向
1.4.3 环境变量相关的参数
其实还有一个参数 char* env[ ]——>存储环境变量向量表
因此我们可以知道了两张重要的向量表:(1)命令行参数表 (2)环境变量表
1.4.4 理解环境变量的全局属性
环境变量是系统提供的一组name=value形式的变量,不同的环境变量有不同的用户,通常具有全局属性
如何理解全局属性,其实本质上就是由于环境变量表,我们所执行的进程都是子进程,bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息,然后子进程会继承父进程的环境变量!! 因此环境变量表会被继承下去!!就相当于是全局了!!
根据前面的知识。如果是先创建了进程,然后再修改了环境变量,那么新创建的子进程必然会被继承下去(共享数据),但如果创建了子进程然后修改了环境变量并不会影响父进程的环境变量,因为会发生写时拷贝
1.4.5 本地变量vs环境变量
本地变量只会在bash内部有效,不会被继承
set ——>查看所有的环境变量的本地变量
export ……——>将本地变量变成环境变量
unset……——>清除环境变量
什么情况下需要本地变量呢??
——>就是只希望在bash里面使用但是不希望被子进程继承下去的,比如说我们的命令行提示符,如果是root用户就是# 如果是普通用户就是$
1.4.6 常规命令vs内建命令
之前我们提到过,如果我们不小心将环境变量覆盖了,那么就会导致大部分的指令用不了,但是并不是所有的指令都用不了!! 比如echo、pwd、cd…… 因为他们是内建命令
常规命令:通过创建子进程完成的
内建命令:bash不创建子进程,而是由自己亲自执行,类似与bash调用了自己一些的,或者是系统提供的函数
所以一般的命令,我们可以知道bash应该是使用了fork函数创建了子进程去完成的,但是内建命令就是直接去完成
1.4.7 模拟实现内建命令cd
chdir
1.5 再次总结环境变量
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,通常具有全局属性,并且一般来讲都有其特殊的用途(比如我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但 是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。)
环境变量相关命令:
1、echo: 显示某个环境变量值
2. export: 设置一个新的环境变量
3. env: 显示所有环境变量
4. unset: 清除环境变量
5. set: 显示本地定义的shell变量和环境变量
环境变量的组织方式:每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串