美妆网站建设环境分析,企业年金辞职了怎么办,外贸公司出口退税流程,qq是根据哪款软件开发的#x1f493;博主CSDN主页:杭电码农-NEO#x1f493; ⏩专栏分类:Linux从入门到精通⏪ #x1f69a;代码仓库:NEO的学习日记#x1f69a; #x1f339;关注我#x1faf5;带你学更多操作系统知识 #x1f51d;#x1f51d; 程序地址空间 1. 前言2. 在ba… 博主CSDN主页:杭电码农-NEO ⏩专栏分类:Linux从入门到精通⏪ 代码仓库:NEO的学习日记 关注我带你学更多操作系统知识 程序地址空间 1. 前言2. 在bash中查看所有环境变量3. 程序中获取环境变量的方式4. main函数的第三个参数解析5. 本地的与env中的环境变量6. 配置文件与环境变量的全局性7. 内建命令与常规命令8. 程序地址空间初认识9. 深入探究地址空间与物理内存10. 总结 1. 前言
如果你不知道什么是环境变量PATH 请先阅读下面的文章:
初识环境变量
本章重点: 本篇文章着重于完善上一篇文章遗留 的一些环境变量的问题,认识其他几个 常见的环境变量,以及在bash下查看 环境变量和添加环境变量的方式,以及 拓展main函数的第三个参数:env. 最后对程序地址空间的内容开个头! 2. 在bash中查看所有环境变量
在bash中查看所有环境变量: 使用指令: env 可以看见打印出密密麻麻的环境变量 这其中不需要我们全部记住,只需简单 的认识几个常见的环境变量即可!
环境变量PWD: 记录当前路径,你以为平时执行的 pwd指令是怎么知道当前路径的? 稍加思考就能窥探,pwd实际上调用 了PWD环境变量! 环境变量HOME 我们平时使用的指令:cd ~进入 家目录,哪儿是家目录?环境变量 HOME里面的内容就是家目录! 简述登录Xshell时,所要做的事 根据以上对环境变量的认识,我们发现 登录xshell时我们用root账户登录就 会跑到root的家目录下,这是因为在 启动Linux时,OS帮我们做了一些事情 输入用户名,密码 认证信息是否正确 形成环境变量(PATH,PWD,等等) 根据用户名初始化HOME环境变量 HOMEroot或HOMEXXX cd $HOME(进入家目录) 3. 程序中获取环境变量的方式
我们知道,Linux是由C语言写的 所以这里的程序我们默认是C程序 使用函数: getenv() 使用方法如下:
char* p NULL;
p getenv(PATH);p就能获取环境变量PATH的内容了
即函数的参数是环境变量的名字 返回值是环境变量的内容! 4. main函数的第三个参数解析
不卖关子,直接写出来:
int main(int argc,char* argv[],char* env[])第三个参数为env,是不是很熟悉? 没错,第三个参数就是环境变量 它和第二个参数一样是指针数组 它指向环境变量表,环境变量表中的 内容和在bash中使用env打印的一样! 到目前为止了解到,系统在启动 程序时会给main函数提供两张表:
命令行参数表环境变量表
通过下面的代码查看环境变量表:
#includestdio.h
int main(int argc,char* argv[],char* env[])
{for(int i0;env[i]!NULL;i){printf([%d]: %s\n,i,env[i]);}return 0;
}5. 本地的与env中的环境变量
我们可以在bash中直接定义环境变量 使用指令: 环境变量名内容 比如: 用户自己定义的环境变量是本地的 而env并不能查看本地的环境变量 所以使用env查找刚才定义的环境变量 时,实际上会找不到! 如果想要我们定义的环境变量 被放在系统的环境变量表中应该怎么做? 使用指令: export 环境变量名 还可以使用export定义环境变量: 6. 配置文件与环境变量的全局性
根据上面的一些信息我们可以推论: 在修改/定义环境变量时,实际上 修改/定义的是bash进程内部的 环境变量信息,每一次重新登录都会 形成新的bash解释器,并且新形成 的bash解释器会自动从家目录下 的bash_profile文件中读取信息形成 一份新的环境变量表! 所以为啥每次重新启动bash后 我们自己定义/修改的环境变量 就不见了?因为它并没有被保存在 配置文件bash_profile中!
查看配置文件bash_profile: 当我们在配置文件中加上自己想要 一直存在的环境变量时,此时bash再 次启动后,这个环境变量就会被放到 环境变量表中! 并且在创建子进程时 这张表会通过main函数的参数传递 给子进程,所以子进程有了和父进程 一样的环境变量表,而子进程创建孙子 进程时又会将子进程的表给孙子进程 所以说,环境变量具有全局性! 本地变量 VS 环境变量
1. 本地变量只在bash进程内部有效,不会被子进程继承
2. 环境变量通过让所有子进程继承的方式,实现自身的全局性7. 内建命令与常规命令
我们知道一个事实,bash中的指令 可以直接使用,不用加./是因为它的 路径在环境变量PATH中,所以我们 将PATH置空后,这些命令就不能运行了! 我们会发现一个问题,PATH被置空后 确实有些命令是跑不了了.但是某些 命令还是能跑,比如pwd命令还能正常 输出,这是为啥呢?
Linux下的命令父分类:
常规命令:bash创建子进程执行的内建命令:bash自己执行的(类似于一个函数)
很明显pwd是内建命令,echo也是 内建命令,难道你就没有一个疑惑吗? 为什么我们自己定义的环境变量在 环境变量表env中找不到,但是echo 命令却可以将它的内容打印出来? echo程序也是bash的一个进程 为什么它能获取我们定义的环境变量? 答案是echo是内建命令,是父进程 自己内部执行的,所以它可以看见 父进程的变化,但是其他的子进程不能 接受父进程的本地变量,所以看不见! 8. 程序地址空间初认识
C/C程序员认为,程序的内存分布是这样的: 堆是向上增长的,栈是向下增长的 这个我们在以前的学习中以及有所 了解了,那为什么这里还要提呢?
有两个目的:
再对以前的知识做复习在原有知识的基础上拓展
这其中有两个地方需要注意: 在写C程序时定义的常量字符串 实际上在上面区域的正文代码区 因为它和正文代码区紧挨着,所以 常量区的字符串不允许修改! 第二点是,栈虽然说是向下增长的 但是栈中的数组,结构体等结构的 地址是向上增长的,比如说开辟数组 时,开辟十个空间,那么数组中第一个 元素在空间的最下面,也就是地址最低 处,然后依次往上放后面的元素 9. 深入探究地址空间与物理内存
现在写上这样一段代码来深入探究地址:
#include stdio.h
#include unistd.h
#include sys/types.h
#includestdlib.h
int main()
{ int idfork(); int tmp10; if(id0)//子进程执行的代码 { tmp20; while(1) { printf(子进程,tmp: %d,tmp: %p\n,tmp,tmp); sleep(1); } } if(id1)//父进程执行的代码 { while(1) { printf(父进程,tmp: %d,tmp: %p\n,tmp,tmp); sleep(1); } } return 0;
} 我们发现,tmp的值在父子进程中 是不同的,可以我们暂时可以理解, 是因为写时拷贝, 但是相同的地址 为什么会有不同的值? 这就有一点 挑战我们之前学习的知识了!
以目前的知识储备是无法想明白这个问题的 但是我们可以得出一个小结论: 我们平时写的堆区,栈区,静态区 等等区,并不是真实的物理地址! 因为一个物理地址不可能有两个值 那么真实的物理地址到底是什么? 如果这个不是真实的物理地址那么 这个地址又是什么东西呢?我们打印 出来的地址又是什么东西?以上内容 将在下一篇文章讲解! 10. 总结
了解环境变量相关知识可以更好的 理解操作系统在启动时所做的工作, 以及可以更好的了解进程在运行的 时候需要的一些数据从何而来!
本篇文章不再做拓展,更多内容 将在下一篇文章中讲解 下期预告:程序地址空间