赞
踩
主页:醋溜马桶圈-CSDN博客
目录
echo $NAME //NAME:你的环境变量名称
- echo: 显示某个环境变量值
- export: 设置一个新的环境变量
- env: 显示所有环境变量
- unset: 清除环境变量
- set: 显示本地定义的shell变量和环境变量
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串
- #include <stdio.h>
- int main(int argc, char* argv[], char* env[])
- {
- int i = 0;
- for (; env[i]; i++) {
- printf("%s\n", env[i]);
- }
- return 0;
- }
- #include <stdio.h>
- int main(int argc, char* argv[])
- {
- extern char** environ;
- int i = 0;
- for (; environ[i]; i++) {
- printf("%s\n", environ[i]);
- }
- return 0;
- }
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- printf("%s\n", getenv("PATH"));
- return 0;
- }
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- char* env = getenv("MYENV");
- if (env) {
- printf("%s\n", env);
- }
- return 0;
- }
直接查看,发现没有结果,说明该环境变量根本不存在
- 导出环境变量
export MYENV="hello world"- 再次运行程序,发现结果有了!说明:环境变量是可以被子进程继承下去的!
在C语言的时候,有这样的空间布局图
可是我们对他并不理解
来段代码感受一下
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- int g_val = 0;
- int main()
- {
- pid_t id = fork();
- if (id < 0) {
- perror("fork");
- return 0;
- }
- else if (id == 0) { //child
- printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
- }
- else { //parent
- printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
- }
- sleep(1);
- return 0;
- }

输出结果:
- //与环境相关,观察现象即可
- parent[2995]: 0 : 0x80497d8
- child[2996] : 0 : 0x80497d8
我们发现,输出出来的变量值和地址是一模一样的,很好理解呀,因为子进程按照父进程为模版,父子并没有对变量进行进行任何修改。可是将代码稍加改动:
- #include <stdio.h>
- #include <unistd.h>
- #include <stdlib.h>
- int g_val = 0;
- int main()
- {
- pid_t id = fork();
- if (id < 0) {
- perror("fork");
- return 0;
- }
- else if (id == 0) { //child,子进程肯定先跑完,也就是子进程先修改,完成之后,父进程再读取
- g_val = 100;
- printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
- }
- else { //parent
- sleep(3);
- printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
- }
- sleep(1);
- return 0;
- }

输出结果:
- //与环境相关,观察现象即可
- child[3046]: 100 : 0x80497e8
- parent[3045] : 0 : 0x80497e8比
我们发现,父子进程,输出地址是一致的,但是变量内容不一样!能得出如下结论:
- 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
- 但地址值是一样的,说明,该地址绝对不是物理地址!
- 在Linux地址下,这种地址叫做 虚拟地址
- 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理
OS必须负责将 虚拟地址 转化成 物理地址
所以之前说‘程序的地址空间’是不准确的,准确的应该说成 进程地址空间
说明:
上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址!
上图是Linux2.6内核中进程队列的数据结构
从该结构中,选择一个最合适的进程,过程是怎么的呢?
- 从0下表开始遍历queue[140]
- 找到第一个非空队列,该队列必定为优先级最高的队列
- 拿到选中队列的第一个进程,开始运行,调度完成!
- 遍历queue[140]时间复杂度是常数!但还是太低效了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。