【Linux 学习计划】-- 命令行参数 | 环境变量
目录
命令行参数
环境变量
环境变量的本质是什么?
相关配置文件
修改环境变量的相关操作
代码获取env —— environ
内建命令
结语
命令行参数
试想一下,我们的main函数,也是一个函数,那么我们的main函数有没有参数呢?
有的兄弟有的,main函数其实可以有三个参数,但是现在我们只讲其中两个,因为最后一个和下文要讲的环境变量有关
而前两个分别是argc和argv,不理解没关系,我们直接来看代码:
我们可以看到,我们命令行上的参数,直接在执行文件后面加的东西,会直接被main函数的两个参数给捕捉到
其中,argc就是后面加上的参数的数量加上执行文件的名字本身
而 argv 则是这些变量的具体字符串
那么这些个参数具体有什么用呢?换句话说,看到这样子的执行方式,有没有感觉有一点熟悉
这不就是我们指令的执行方式吗?!!
我们的 ls -a -l,rm -r -f 等等,这些都是执行文件加上指令啊!
所以,main函数参数的本质其实就是分配给一个可执行文件的不同任务,每一个任务都有对应的效果,写一个小代码就明白了:
而这些工作在未来,都是交给子进程去做的
但是有一个问题,进程不是互相之间独立的吗?为什么子进程能做?main函数在外面的命令行参数,本质上不是传给父进程的吗?
这其实是后面关于程序地址空间的相关内容,这里不做介绍,只需要知道——子进程刚创建的时候,数据都是拷贝自父进程的,所以子进程能有一样的数据,也就能够使用、执行对应的任务了
但是由于是拷贝,所以子进程能够看见父进程的数据,但是父进程看不到子进程的
环境变量
先来看一看环境变量中的 PATH:
这个路径,就是平常程序要找相关可执行文件(指令)时候会找的路径
换句话说,我们平常写完可执行程序之后,都需要 ./XXX进程运行,但是指令则不需要,这是因为默认环境变量中的PATH已经将这些路径给记录下来了,所以不用./
所以,只要我们将自己的路径放在里面,我们的程序也能不用 ./ 而是直接执行是吗?yes
环境变量的本质是什么?
在程序开始之前,由于我们的bash(命令行解释器)也是一个进程,所以系统会将部分文件直接加载进bash进程之中,通过什么方式?mian函数的命令行参数!!(这个在下文讲)
相关配置文件
当我们来到自己的家目录下,我们可以看到里面有两个隐藏文件,我们可以打开其中的.bash_profile
我们可以清楚地看到第10行,这里面就是我们的PATH地址
而我们现在在这后面加上我们自己的地址,这时候就代表:
因为系统在我们登录的时候,就是将着些个文件加载进bash进程之中,所以我们现在每一次登PATH 都会是这样
之前的由于我们只是在bash进程内部,比如说用PATH=$PATH:自己的地址 这样的方式进行更改,在我们退出登录之后,他就没了,下一次登录就是默认的样子,因为这只是内存级的
现在我们改完配置文件之后重新登录:
就可以看见,确实是生效了
修改环境变量的相关操作
首先是查看,这里我们用 echo $XXX 来查看对应的环境变量,其中XXX代表某个环境变量的名字
如果我们想要一键查看所有环境变量的话,我们可以直接使用 env 进行查看:
其中我们也可以看见一些熟悉的变量
接着,如果我们想将一个新的变量变成环境变量的话,我们可以使用export name,反之如果不想让其当环境变量了,就可以使用unset name来进行修改
用了unset之后,确实就没有了
注意,上面这些都是命令行获取环境变量的相关操作
首先,这些操作都是内存级的。下次登录的时候默认就恢复了,所以可以随便改(别改到配置文件就好)
其次,我们还可以使用代码获取对应的环境变量,比如environ,getenv("name")这样的方式,这些我们放在下文,穿插在知识点里面进行讲解
代码获取env —— environ
我们来看这么一个代码,environ 具体是什么我们待会儿说,先来看效果:
这是我们程序运行的结果,可以看到,这不就是我们刚刚直接用env指令看到的环境变量吗?
但是,为什么我们能通过指令来看到这些环境变量呢?
首先,环境变量是从磁盘的配置文件,在我们登录的时候加载进bash进程里面的
今天我们写了一个新进程,而这个进程必然是bash用fork创建出来的子进程,后面在学地址空间的时候就会知道,子进程的数据就是拷贝自父进程的
那么这个时候,我们自然就能够看到父进程(bash)的相关数据咯
至于是怎么看到的?里面的environ,就是 char* envp[ ] ,也就是我们前文提到的main函数的第三个参数
我们可以这么理解,在bash进程启动的时候,默认会给子进程创建两张表,一张是argv也就是指令表,还有一张就是环境变量表——即环境变量也是被管理起来的
而这个environ,就是这个环境变量表的头指针
这也就是为什么我们在代码就能够获得环境变量
那还有别的用代码获取环境变量的方式吗?这样一次性获取太多了,我要固定获取某一个环境变量的方式有吗?
有的兄弟有的 —— getenv("name")
比如这样写,但是需要注意的是,这个函数需要包含头文件stdlib.h
综上,我们现在获取环境变量的方式有三种:
- environ指针
- main函数参数
- getenv
内建命令
不知道各位在上面看到export的时候,有没有觉得有些奇怪
export不是一个指令吗?那照我们前面学的,bash会开一个子进程来执行他
但是,子进程可以看见父进程的数据,因为子进程的创建就是拷贝自父进程
但是我们今天用export将变量变成环境变量,这样父进程不是看见了子进程的数据吗?这对吗兄弟?
对的兄弟对的,因为export这样的命令并不是普通的命令,他有一个一个名称叫做内建命令
如果说别的比如 ls 指令,是通过fork然后让子进程跑起来,那么export就好像直接是void export()这样,直接写函数实现,所以他根本就没有创建子进程,这也就是为什么变量能变成环境变量
比如echo也是一个内建命令
我们可以做一个测试,我们的PATH不是负责管理指令的路径吗?如果PATH直接变成空,那么所有的普通指令不就跑不了了吗:
结语
这篇文章到这里就结束啦!!~( ̄▽ ̄)~*
如果觉得对你有帮助的,可以多多关注一下喔