[Linux 进程(四)] 再谈环境变量,程序地址空间初识

在这里插入图片描述

文章目录

  • 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.h>int 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.h>int 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命令行的一个函数。

原来pwd,echo都是内建命令。
那为什么内建命令就直接能读取环境变量呢?
内建命令是shell内部的一个函数,父进程内部执行,它是可以直接看到父进程内部的,当然可以直接读取shell内部定义的本地变量!

2.5 环境变量相关的命令

  1. echo: 显示某个环境变量值
  2. export: 导出一个新的环境变量
  3. env: 显示所有环境变量
  4. unset: 清除环境变量
  5. set: 显示本地定义的shell变量和环境变量
    在这里插入图片描述

3、程序地址空间

C/C++程序员认为,程序内存分布是这样子的:
在这里插入图片描述
我们写一段代码验证一下:

#include <stdio.h>
#include <stdlib.h>int 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、栈区之上先是命令行参数,再是环境变量,不断向上增上的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/242371.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

maven 基本知识/1.17

maven ●maven是一个基于项目对象模型(pom)的项目管理工具&#xff0c;帮助管理人员自动化构建、测试和部署项目 ●pom是一个xml文件&#xff0c;包含项目的元数据&#xff0c;如项目的坐标&#xff08;GroupId,artifactId,version )、项目的依赖关系、构建过程 ●生命周期&…

list列表可编辑状态

有时候list需要修改或选择属性,mfc自带的只能显示内容,基本上是不可以修改,为了实现这个功能需求,需要完成一下步骤转换. 第一步记录选择的单元格. 第二步创建一个编辑框CComboBox对象, 设置字体,窗口属性. 第三步获取选中单元格的位置信息. 第四步获取单元格内容信息. 第五步…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖微信小程序端(十三)

地址簿相关功能 1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计1.1.3 表设计 1.2 代码实现1.2.1 Mapper层1.2.2 Service层1.2.3 Controller层 1.1 需求分析和设计 1.1.1 产品原型 地址簿&#xff0c;指的是消费者用户的地址信息&#xff0c;用户登录成功后可以维护自己的地…

Kafka Console Client 的 Consumer Group

以往使用 kafka-console-consumer.sh 消费 Kafka 消息时并没有太在意过 Consumer Group&#xff0c;在命令行中也不会使用 --group 参数&#xff0c;本文针对 Kafka Console Client 命令行中的 Consumer Group 进行一次统一说明。 1. 如不设置 --group 参数会自动生成一个 Con…

JVM:Java类加载机制

Java类加载机制的全过程&#xff1a; 加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的&#xff0c;类型的加载过程必须按照这种顺序按部就班地开始&#xff0c;而解析阶段则不一定&#xff1a;它在某些情况下可以在初始化阶段之后再开始&#xff0c; 这是为了支持Java…

Java编程练习之this关键字(2)

this关键字除了可以调用成员变量或成员方法之外&#xff0c;还可以作为方法的返回值。 示例&#xff1a;创建一个类文件&#xff0c;在类中定义Book类型的方法&#xff0c;并通过this关键字进行返回。 public class Book{ public Book getBook(){ return this; } } 在getB…

宿舍人走断电系统的重要性

宿舍人走断电系统石家庄光大远通电气有限公司公寓智能用电管理系统适合集体公寓、学生宿舍等应用场景&#xff0c;具备多种性能&#xff0c;满足多种形式需求&#xff0c;解决方案面向实际&#xff1b;集计量控制、违规用电管理、用电过程管理等功能于一体。系统采用集中控制&a…

大创项目推荐 深度学习验证码识别 - 机器视觉 python opencv

文章目录 0 前言1 项目简介2 验证码识别步骤2.1 灰度处理&二值化2.2 去除边框2.3 图像降噪2.4 字符切割2.5 识别 3 基于tensorflow的验证码识别3.1 数据集3.2 基于tf的神经网络训练代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x…

使用Scrapy 爬取“http://tuijian.hao123.com/”网页中左上角“娱乐”、“体育”、“财经”、“科技”、历史等名称和URL

一、网页信息 二、检查网页&#xff0c;找出目标内容 三、根据网页格式写正常爬虫代码 from bs4 import BeautifulSoup import requestsheaders {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/53…

C#操作pdf之使用itext实现01-生成一个简单的table

创建.net 8控制台项目 安装itext <PackageReference Include"itext" Version"8.0.2" /><PackageReference Include"itext.bouncy-castle-adapter" Version"8.0.2" /><PackageReference Include"itext.bouncy-cast…

【从零开始学习Java重要知识 | 第三篇】暴打ReentrantLock底层源码

目录 前言&#xff1a; 前置知识&#xff1a; 什么是公平锁与非公平锁&#xff1f; 尝试自己构造一把锁&#xff1a; ReentrantLock源码&#xff1a; 加锁&#xff1a; 解锁&#xff1a; 总结&#xff1a; 前言&#xff1a; 在并发编程中&#xff0c;线程安全是一个重…

【机器学习】调配师:咖啡的完美预测

有一天&#xff0c;小明带着一脸期待找到了你这位数据分析大师。他掏出手机&#xff0c;屏幕上展示着一份详尽的Excel表格。“看&#xff0c;这是我咖啡店过去一年的数据。”他滑动着屏幕&#xff0c;“每个月的销售量、广告投入&#xff0c;还有当月的气温&#xff0c;我都记录…

day16 DOM(2)——获取设置表单的值

目录 操作表单元素属性H5自定义属性——data 操作表单元素属性 表单很多情况&#xff0c;也需要修改属性&#xff0c;比如点击眼睛&#xff0c;可以看到密码&#xff0c;本质是把表单类型转换成文本框正常的有属性有取值的&#xff0c;跟其它的标签属性没有区别 获取&#xff…

web蓝桥杯真题--11、蓝桥知识网

介绍 蓝桥为了帮助大家学习&#xff0c;开发了一个知识汇总网站&#xff0c;现在想设计一个简单美观的首页。本题请根据要求来完成一个首页布局。 准备 开始答题前&#xff0c;需要先打开本题的项目代码文件夹&#xff0c;目录结构如下&#xff1a; ├── css │ └──…

开源进程/任务管理服务Meproc使用之HTTP API

本文讲述如何使用开源进程/任务管理服务Meproc的HTTP API管理整个服务。 Meproc所提供的全部 API 的 URL 都是相同的。 http://ip:port/proc例如 http://127.0.0.1:8606/proc在下面的小节中&#xff0c;我们使用curl命令向您展示 API 的方法、参数和请求正文。 启动任务 …

C++I/O流——(4)格式化输入/输出(第二节)

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 含泪播种的人一定能含笑收获&#xff…

【前端设计】流光按钮

欢迎来到前端设计专栏&#xff0c;本专栏收藏了一些好看且实用的前端作品&#xff0c;使用简单的html、css语法打造创意有趣的作品&#xff0c;为网站加入更多高级创意的元素。 css body{height: 100vh;display: flex;justify-content: center;align-items: center;background…

使用 crypto-js 进行 AES 加解密操作

在前端开发中&#xff0c;数据的加密和解密是为了保障用户隐私和数据的安全性而常见的任务。AES&#xff08;Advanced Encryption Standard&#xff09;是一种对称密钥加密算法&#xff0c;被广泛用于保护敏感信息的传输和存储。本文将介绍 AES 加解密的基本原理&#xff0c;并…

智慧文旅运营综合平台:重塑文化旅游产业的新引擎

目录 一、建设意义 二、包含内容 三、功能架构 四、典型案例 五、智慧文旅全套解决方案 - 210份下载 在数字化浪潮席卷全球的今天&#xff0c;智慧文旅运营综合平台作为文化旅游产业与信息技术深度融合的产物&#xff0c;正逐渐显现出其强大的生命力和广阔的发展前景。 该…

二叉树的直径(LeetCode 543)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述 给你一棵二叉树的根节点&#xff0c;返回该树的直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的长度由它们之间边数…