其实main函数是可以传参数的,也叫做命令行参数。我们这里先介绍main函数的前两个参数
argc代表的是指针数组的元素个数,argv是一个指针数组,指针指向字符串。argv不可能为空,argv【0】存储该进程的名字
例如 ls -a -l 那么argv就会存储ls,-a,-l,以空格为分隔符,argc则为3
然后main函数可以通过字符串来进行映射分流,实现不同的功能
命令行参数是让系统函数存在选项的重要概念
我们也终于理解历史学的指令和选项是什么关系了 (指令里面含有main函数,将选项作为字符串传参,然后进行映射分流)
学完上面的命令行参数后,我们发现在执行自己实现的指令的时候往往要加上./,而系统里的指令却不用,直接输入名字就好了,这是为什么呢?这里就和我们的环境变量有关系了
要加上./是因为要让系统在当前目录中去寻找这个文件,不然的话系统找不到
而系统的指令默认是在$PATH这个环境变量中去寻找的
那么$PATH具体是什么呢?我们可以通过echo查看一下——echo $环境变量名
可以看到本质上就是存储了一个个路径,以:为分隔符隔开
除了PATH这个环境变量,系统中还有其他大量的环境变量
例如 HOME——查看自己的家目录
SHELL——查看当前SHELL
每个环境变量都有自己的特定功能,任何进程在启动的时候都会获得命令行变量表和环境变量表
环境变量是以什么形式存储的?
本质上环境变量都为一个个字符串,所以我们用指针数组存储他们首元素的地址,就能找到对应的环境变量了,所以环境变量表本质上就是一个指针数组
父子进程的环境变量从哪来?
首先我们知道bash进程上的命令行(名义上的父进程)都是bash的子程序,子进程的命令行参数和环境变量都由父进程bash传递
那我们的bash是如何在启动的时候就知道环境变量的呢?
其实环境变量都存储在相关的配置文件中,bash启动的时候就会读取配置文件然后形成相关的环境变量表
每个进程都有自己的环境变量吗,还是他们共享一份?
父进程创建子进程的时候,会拷贝一份环境变量表给子进程,并将一些需要修改的信息进行修改(例如当前路径,用户名等),这样就实现了环境变量的全局性。所以每个进程都有自己的环境变量,而不是独享一份
查看环境变量的三种方法
1.通过main函数的第三个参数
#include
int main(int argc,char* argv[],char* env[]) { //argc : 命令行参数的个数, 本质上就是argv数组的元素个数 //argv :具体的命令行参数 // envp : 环境变量的值 for(int i=0;i 2.通过第三方变量environ获取
#include
int main(int argc,char* argv[]) { extern char** environ; for(int i=0;environ[i]!=NULL;i++) { printf("%s\n",environ[i]); } return 0; } libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明
3.通过getenv()或者putenv()来访问特定的环境变量
#include
#include #include int main() { printf("%s\n",getenv("PATH")); return 0; }
关于环境变量的一些指令
1. echo: 显示某个环境变量值
2. export: 设置一个新的环境变量
3. env: 显示所有环境变量
4. unset: 清除环境变量
5. set: 显示本地定义的shell变量和环境变量
这里看到可以用export设置新的环境变量,但是我们设置完后关掉shell再打开就会失效了,这是为什么呢?
原因是这里export的只是一个本地变量,不会被继承,只存在当前进程中,而我们的环境变量本质上是去配置文件中读取然后形成的,所以关掉后本地变量会消失,而环境变量却依然可以使用
如果真要修改环境变量,就要去修改相关的配置文件
当PATH被设置为空的时候,为什么echo却能访问进程的本地变量呢?
linux的两种命令
1.常规命令:在磁盘中真实存在的,需要shell fork让子进程执行的——诸如ls,pwd...
2.内建命令:shell命令行的一个函数,当然可以访问shell的本地变量
常规命令需要shell创建子进程并去PATH中获取,但是此时PATH为空
echo则是shell的一个函数,可以理解为父进程的函数,可以直接执行
———————————————————————————————————————————