分类信息网站如何做优化,网站站内关键词优化,公司网站能否申请国外免费空间,网站建设公司优惠大酬宾活动文章目录 1、前言2、环境变量2.1 main函数第三个参数 -- 环境参数表2.2 本地环境变量和env中的环境变量2.3 配置文件与环境变量的全局性2.4 内建命令与常规命令2.5 环境变量相关的命令 3、程序地址空间 1、前言
上一篇我们讲了环境变量#xff0c;如果有不明白的先读一下上一… 文章目录 1、前言2、环境变量2.1 main函数第三个参数 -- 环境参数表2.2 本地环境变量和env中的环境变量2.3 配置文件与环境变量的全局性2.4 内建命令与常规命令2.5 环境变量相关的命令 3、程序地址空间 1、前言
上一篇我们讲了环境变量如果有不明白的先读一下上一篇文章环境变量讲解 本篇文章我们继续完善环境变量这章剩下的内容以及main函数第三个参数的详解进程地址空间的初始。
2、环境变量
2.1 main函数第三个参数 – 环境参数表
看完上一篇文章的同学肯定知道了如何查看环境变量命令行输入 env 我们查看一下
我们main函数的参数列表中第三个就是环境变量表没错它里面就记录着这些环境变量。 它与第二个参数一样都是char类型的指针数组。我们写一段代码打印一下环境变量表中的内容
#include stdio.hint main(int argc, char* argv[], char* env[])
{int i 0;for( ; env[i]; i){printf(env[i]: %s\n, i, env[i]);}return 0;
}我们发现main函数的第三个参数环境参数表跟我们env所查出来的内容是一模一样的。 这是因为我们程序在运行时环境变量是系统给传的。 问题 那这个给程序传环境变量的系统是谁 在学习fork的时候我们知道fork()函数是可以创建子进程的。同时我们也知道命令行启动的进程都是shell/bash的子进程子进程的命令行参数和环境变量是父进程bash给传递的 问题 那父进程bash的环境变量信息又是从哪里来的 我们在上一篇中讲到PATH内容修改后下一次启动Xshell时PATH内容又自动恢复了。这其实是我们直接更改了bash进程内部的环境变量信息 每一次重新登录都会给我们形成新的bash解释器并且新的bash解释器自动从 哪里 读取自己的环境变量表信息 虽然我们现在还不知道父进程环境变量哪里来的但是环境变量存在哪我就直接说了环境变量信息是以脚本配置文件的形式存在的 在登录目录下有一个.bash_profile脚本文件每一次登录的时候bash进程都会读取 .bash_profile配置文件中的内容为我们bash形成一张环境变量表信息
2.2 本地环境变量和env中的环境变量
我们可以在bash中直接定义环境变量环境变量名 内容 我们来试一下
用户定义的环境变量是本地的env是查看不了本地环境变量的。
如果我们想要把我们自己定义的环境变量导出到env所能查看到的环境变量中我们可以使用以下命令
export 环境变量名还可以直接使用export定义环境变量
当我们把自己定义的环境变量放入了bash的环境变量后我们在main函数所打印的环境变量中能不能找到呢我们试一下
我们在命令行中输入的命令都是bash的子进程这就验证了子进程的环境变量是由父进程给传递的。
2.3 配置文件与环境变量的全局性
问题 我们要是重新登录Xshell的话我们刚导出的环境变量还在吗 在不在我们测试一下就出来了
明显是不在的我们刚才导出是直接给bash进程的内部导出了。我们重新启动后 .bash_profile脚本文件会重新执行bash进程内部的环境变量会重新读取并形成一份新的环境变量表。 如果我们想要每次登录后bash的环境变量表都有我们自己添加的环境变量我们就需要在 .bash_profile脚本文件中添加此后再登录后bash的环境变量表中就有了添加的环境变量。 我们再介绍一个获取环境变量的系统调用函数const char ** environ 我们发现environ的类型是一个二级指针这里不卖关子了它其实指的是环境变量表首元素 我们写一段代码将其内容打印出来
#include stdio.h
#include unistd.hint main()
{extern char** environ;int i 0;for(i 0; environ[i]; i){printf(environ[%d]: %s\n, i, environ[i]);}return 0;
}问题 大家有没有想过如果我们本地环境变量子进程会将我们添加的本地环境变量也继承下来吗 我们做一下实验 显然是没有的这里细心的人会发现echo为什么就继承下来了其实echo不是子进程别急下一个话题我们就会讲到。如果我们将本地变量导出到系统环境变量中子进程就会将其继承下来。 总结 1、迄今为止我们学到了三种获取环境变量的方式
getenv();main函数传参方式extern char** environ;
2、bash再去创建子进程时bash会给子进程传递一份同样的环境变量子进程再创建子进程天然的就继承了父进程的环境变量表也就间接获取了bash所传递的环境变量所以系统环境变量具有全局属性
3、本地环境变量 vs 系统环境变量
本地环境变量只在bash进程内部有效不会被子进程继承下去系统环境变量通过让所有子进程继承的方式实现自身的全局性
2.4 内建命令与常规命令
通过上一篇的学习我们知道了bash自己的指令可以直接使用不用加 ./因为这些指令在系统默认路径PATH下现在我们将PATH置空这些指令就运行不了了
我们发现有些指令确实不能运行了但是有些指令仍然可以运行。这是为什么呢 Linux下命令分为两类
常规命令shell通过fork创建子进程让子进程执行的内建命令shell命令行的一个函数。
原来pwdecho都是内建命令。 那为什么内建命令就直接能读取环境变量呢 内建命令是shell内部的一个函数父进程内部执行它是可以直接看到父进程内部的当然可以直接读取shell内部定义的本地变量
2.5 环境变量相关的命令
echo: 显示某个环境变量值export: 导出一个新的环境变量env: 显示所有环境变量unset: 清除环境变量set: 显示本地定义的shell变量和环境变量
3、程序地址空间
C/C程序员认为程序内存分布是这样子的 我们写一段代码验证一下
#include stdio.h
#include stdlib.hint uninit_global;
int init_global 0;
int main(int argc, char* argv[], char* env[])
{printf(code address: %p\n, main); // 代码区const char* str Hello Linux!\n;printf(read only char address: %p\n, str); // 字符常量区printf(init global value address: %p\n, init_global);printf(uninit global value address: %p\n, uninit_global);char* heap1 (char*)malloc(sizeof(char)*100);char* heap2 (char*)malloc(sizeof(char)*100);char* heap3 (char*)malloc(sizeof(char)*100);char* heap4 (char*)malloc(sizeof(char)*100);static int a 0;printf(heap1 address: %p\n, heap1); printf(heap2 address: %p\n, heap2);printf(heap3 address: %p\n, heap3);printf(heap4 address: %p\n, heap4);printf(stack address: %p\n, str);printf(stack address: %p\n, heap1);printf(stack address: %p\n, heap2);printf(stack address: %p\n, heap3);printf(stack address: %p\n, heap4);printf(a address: %p\n, a);int i 0;for(i 0; i argc; i){printf(argv[%d]: %p\n, i, argv[i]);}for(i 0; env[i]; i){printf(env[%d]: %p\n, i, env[i]);}return 0;
}我们在这里就能看出来 1、堆上的地址内存的使用是不断增大 2、栈上的地址内存的使用是不断减小的但是在我们c/c中定义数组、结构体或者整型它们的地址是向上增长的。比如开辟一个十个元素的整型数组一次整体开出来首元素地址在最低因此遍历时是操作。 3、static修饰的静态成员变量其实就是全局变量他就放在已初始化全局变量区所以它在全局就一份。 4、栈区之上先是命令行参数再是环境变量不断向上增上的。