目录
[Part1. main函数命令行参数](#Part1. main函数命令行参数)
[Part2. PATH环境变量](#Part2. PATH环境变量)
[Part2.1. PATH作用](#Part2.1. PATH作用)
[Part2.2. 查看PATH](#Part2.2. 查看PATH)
[Part2.3. shell执行一条命令流程](#Part2.3. shell执行一条命令流程)
[Part3. 环境变量基础概念](#Part3. 环境变量基础概念)
[Part4. shell操作环境变量](#Part4. shell操作环境变量)
[Part5. C语言操作环境变量](#Part5. C语言操作环境变量)
[Part5.1. main函数参数 envp](#Part5.1. main函数参数 envp)
[Part5.2. getenv 获取指定环境变量](#Part5.2. getenv 获取指定环境变量)
[Part5.3. extern environ 全局变量](#Part5.3. extern environ 全局变量)
[Part6. 环境变量的特性](#Part6. 环境变量的特性)
[Part7. shell脚本](#Part7. shell脚本)
[Part8. 进程地址空间补充](#Part8. 进程地址空间补充)
[Part9. 结语](#Part9. 结语)
前言
在Linux中环境变量是非常重要的存在,接下来来跟随小编的视角来理解一下吧。
let's go!!!!!!!!
Part1. main函数命令行参数
cppint main(int argc, char *argv[]) { for(int i = 0; i < argc; i++) { printf("argv[%d]: %s\n", i, argv[i]); } return 0; } //argc:argument count,命令行参数个数。 //argv:argument vector,字符串数组,存放每一个命令参数。示例:./exe a b
• argc = 3
• argv0 = "./exe",永远是程序本身名字
• argv1 = "a"
• argv2 = "b"
• argv3 = NULL,数组末尾以NULL结尾。
shell把输入的一整行字符串,以空格分割,得到argv数组传给main函数。
很多命令行程序利用argv做不同功能,例如 ls -a,程序读取argv1做分支判断。
Part2. PATH环境变量
Part2.1. PATH作用
PATH保存若干目录路径,shell执行命令时,会依次去PATH内的目录查找可执行程序。
如果程序不在PATH目录,执行就必须写 ./程序名;把程序所在目录加入PATH之后,可以直接输入程序名字运行。
Part2.2. 查看PATH
echo $PATH
多个路径用冒号:分割
/usr/local/bin:/usr/bin:/bin临时添加路径到PATH:
X为你的可执行文件所在绝对路径
PATH=$PATH:X$PATH代表保留系统原有路径,追加新目录X。
这是临时修改,关闭终端就失效。
Part2.3. shell执行一条命令流程
以执行ls举例:
1. bash创建子进程;
2. 在子进程内部,解析命令,在PATH环境变量保存的目录依次搜索ls;
3. 找到可执行文件,调用exec执行程序;
4. 程序运行结束,子进程退出,bash回收僵尸子进程。
Part3. 环境变量基础概念
环境变量格式:名字=内容。
• env:查看全部环境变量;• 环境变量属于进程属性,子进程默认继承父进程全部环境变量。
常用环境变量
echo HOME 当前用户家目录 echo USER 当前登录用户名
echo HISTSIZE history历史命令保存条数 echo HOSTNAME 主机名
echo PWD 当前工作目录 echo OLDPWD 上一次的目录,cd - 依赖这个变量
配置文件
登录bash时,会读取配置文件:
~/.bashrc、~/.bash_profile。
把环境变量写进这两个文件,每次打开终端自动生效。
Part4. shell操作环境变量
1. export 变量名=值:把本地变量导出成环境变量,子进程可以继承;
2. unset 变量名:删除环境变量;
区分本地变量、环境变量
• 直接 i=10,创建本地shell变量,只在当前bash内部生效,子进程拿不到;• export i=10,变成环境变量,fork出来的子进程全部继承。
• set命令可以查看shell所有本地变量+环境变量。
Part5. C语言操作环境变量
Part5.1. main函数参数 envp
cpp// 第三个参数接收全部环境变量 int main(int argc, char *argv[], char *envp[]) { for(int i = 0; envp[i]; i++) { printf("%s\n", envp[i]); } return 0; }main函数第三个参数envp接收进程全部环境变量数组,数组末尾为NULL。
真正程序入口不是main,是_start函数,由_start把argc、argv、envp传递给main。
Part5.2. getenv 获取指定环境变量
cpp头文件:#include <stdlib.h> char *value = getenv("USER"); if(value == NULL) { // 环境变量不存在 } else { printf("USER=%s\n", value); }应用场景:程序读取环境变量做权限判断,例如读取USER,判断当前是什么用户,决定程序是否允许运行。
Part5.3. extern environ 全局变量
cpp#include <stdio.h> extern char **environ; int main() { for(int i = 0; environ[i]; i++) { printf("%s\n", environ[i]); } return 0; }environ是libc提供的全局变量,代表当前进程环境变量数组。
Part6. 环境变量的特性
1. 全局:父进程export导出的环境变量,fork子进程可以继承;
2. 本地shell变量,仅仅当前shell内部使用,子进程不会继承;
3. 子进程修改继承过来的环境变量,不会影响父进程,环境变量随进程地址空间拷贝。
Part7. shell脚本
脚本文件开头必须指定解释器:
!/bin/bash
后面写shell命令
执行脚本: bash 1.sh或者./1.sh 。
Part8. 进程地址空间补充
环境变量存放在进程虚拟地址空间,不是物理内存
fork之后子进程拿到一份拷贝,父子虚拟地址相同,但是物理内存不同,修改互不干扰。
父进程全局变量,fork之后父子虚拟地址一样,但是物理内存不同,子进程修改不会影响父进程。
Part9. 结语
这篇文章我们认识并知道了Linux环境变量的使用,接下来,小编还会带来更多Linux相关的知识,敬请期待~
最后,祝大家可以:春风得意马蹄疾,一日看尽长安花!最后的最后,要是觉得本文还可以的话,可以点点赞,关注小编一波,谢谢大家!~
