文章目录
- 常见环境变量
- 查一个环境变量
- 系统调用接口getenv
- 什么是环境变量?
- 命令行参数
- 向量表
- 两张核心向量表
- 结论
- 证明一下子进程继承了父进程的环境变量?
- export将本地变量变成环境变量
- 本地变量&&内建命令
- 本地变量:只会在本BASH内部有效,不会被继承
- 内建命令
- 总结
- 和环境变量相关的命令
- 通过代码如何获取环境变量的其他方式
常见环境变量
查一个环境变量
echo需要加上$符号才能打印出来环境变量
系统调用接口getenv
char *getenv(const char *name);
在代码中获取一个环境变量
- PATH:Linux系统的指令搜索路径
bash怎么知道指令在哪里?
bash内部维护了PATH环境变量(指令的搜索路径)
which 是如何找到指令路径的?
对PATH进行搜索
修改PATH
PATH=/home/ljh //将PATH修改成只有/home/ljh,大部分指令无法使用
$PATH是内存级的环境变量,修改后重新登陆即可恢复
- SHELL
用的哪一个SHELL,shell有bash等。。 - USER
当前用户是?
有没有权限得先知道你是谁,对权限理解进一步加深,不同用户根据环境变量不同受限制不同
- HOME
家目录
什么是环境变量?
环境变量是系统提供的一组name=value形式的变量,不同的环境变量有不同的用户,通常具有全局属性
命令行参数
int main(int argc,char* argv[])//指针数组,存的是char*,字符串
{}
c = count 个数
v = value
数组里有多少个元素
我们之前学的main函数从来没有参数,那这两个参数是什么呢?管他是啥我先打印出来看看
int i = 0;for(; i<argc ;i++){printf("argv[%d]->%s\n",i,argv[i]);}
结果
打印出来这不是命令行参数吗?
为什么要这么干?
为指令、工具,软件等提供命令行选项的支持!!
例如ls -l 的实现
// if(argc != 2)43 // {44 // printf("Usage: %s -[a|b|c|d]\n",argv[0]);45 // return 0;46 // }47 // 48 // if(strcmp(argv[1],"--help") == 0)49 // { 50 // printf("Usage: %s -[a|b|c|d]\n",argv[0]);51 52 // }else if(strcmp(argv[1],"-a") == 0)53 // {54 // printf("功能1\n");55 // }else if(strcmp(argv[1],"-b") == 0)56 // { 57 // printf("功能2\n");58 // }else if(strcmp(argv[1],"-c") == 0)59 // {60 // printf("功能3\n");61 // }else if(strcmp(argv[1],"-d") == 0)62 // {63 // printf("功能4\n");64 // }else 65 // {66 // printf("default\n");67 // }
向量表
main函数被调用
你以为你写的./mycmd -a -b -c,其实输入的是字符串"./mycmd -a -b -c",然后以空格为分隔符打散放入的argv[ ]数组中,有几个字符串argc就是几,然后传入给main函数。
并且argv数组 最后一个位置是NULL
所以还可以不用argc遍历,直接利用最后一个是NULL来遍历
int i = 0;for(; argv[i] ;i++){printf("argv[%d]->%s\n",i,argv[i]); //命令行参数表}
那这个命令行参数和环境变量有什么关系呢?
还真有点关系,因为main函数还有第三个变量env
int main(int argc,char* argv[],char* env[])
{
}
char* env[](环境变量表)和命令行参数表结构一摸一样
那就打印出来看看
int i = 0;for(; env[i] ;i++){printf("env[%d]->%s\n",i,env[i]); //环境变量表}
结果
打印出来了环境变量
两张核心向量表
- 命令行参数表
- 环境变量表
不要以为一个进程启动就是把程序加载到内存,而是当我们自己的程序变成进程再启动时,一定有人调用main函数,给main函数把这两张表传入
结论
环境变量概念中的具有全局属性是什么意思?
我们所运行的进程,都是子进程,bash本身在启动的时候,会从操作系统的配置文件中读取环境变量信息,子进程会继承父进程交给我的环境变量!
证明一下子进程继承了父进程的环境变量?
思路:自己增加一个环境变量,子进程如果会继承就会被看到
export将本地变量变成环境变量
MY_VAL=123456//本地变量
export MY_VAL=123456//导出环境变量
同样打印环境变量表
int i = 0;for(; env[i] ;i++){printf("env[%d]->%s\n",i,env[i]); //环境变量表}
bash里面有自己定义的MY_VALUE,自己的mycmd子进程也查到了,验证完成。
子进程要修改环境变量不能影响父进程的环境变量,要发生写时拷贝
以前main函数从来没传入env,那么子进程是如何继承的?
第1种直接传入
第2种继承方式,到地址空间再谈
本地变量&&内建命令
本地变量:只会在本BASH内部有效,不会被继承
什么时候我的进程需要本地变量呢?
比如ps1搞出了命令行的格式 user hostname w工作目录 $
所以我们需要一些只在bash内部的符号,不要被子进程继承下去,所以有了本地变量的概念
内建命令
问题:echo要不要创建子进程,如果创建,那么它无法继承bash的本地变量,但是这里却打印出来了,为什么呢?
王婆(bash)说媒 如果这个媒特别难说,那么就要创建子进程,但是如果这个媒很有把握,那王婆还是愿意自己上的
所以echo是内建命令
同样cd 也是内建命令 - 系统调用chdir()
sleep(15);18 printf("change begin\n"); //目录切换,内建命令cd模拟19 if(argc == 2)20 {21 chdir(argv[1]);22 }23 24 sleep(15);25 printf("change end\n");
我们可以模拟cd命令,利用系统调用chdir()更改自己的工作目录,而不是创建子进程
如果我们今天自己写的mycmd是写的bash本身的话,他不给你创建子进程同样利用chdir改变工作目录cwd
注意
./mycmd / 更改本身的cwd
而pwd创建子进程继承了bash,bash又没改,所以还是原来的工作目录,所以只能ls /proc去看cwd
总结
和环境变量相关的命令
不同的环境变量用途不同,所以需要具体问题具体分析
进程 环境变量 进程地址空间 三位一体 进程的概念再也不是问题
通过代码如何获取环境变量的其他方式
通过第三方变量environ获取
int main(int argc,char* argv[])//指针数组7 { 8 extern char** environ; //C语言提供的全局变量,形参中不用再传递env环境变量表了 9 int i = 0; 10 for(; environ[i] ;i++) //二级指针 指向char* 环境变量表 ,类似于形参char* env[]数组退化为指针char ** env 11 { 12 printf("%d : %s\n",i,environ[i]); 13 } return 0;}