深入Linux系列之环境变量
深入Linux系列之环境变量
那么在之前的内容中,我们已经介绍了我们Linux进程的一些关键属性,例如进程编号以及进程状态和进程优先级,那么本篇文章接介绍Linux的环境变量这一知识点,那么废话不多说,我们进入环境变量的·讲解
1.引入
那么我们目前已经十分熟悉我们的Linux操作系统了,那么我们可以通过输入命令行的方式来与机器进行交互,在我之前的文章中我也介绍过,那么我们在终端输入的这一行一行的指令,那么这些指令的本质其实是在某个特定路径下的可执行文件,那么我们命令行解释器的工作则是首先获取用户键盘输入的指令,然后将其解析分为指令部分与参数部分,然后到特定的路径下去进行寻找匹配我们指令所对应的可执行文件,然后用fork系统调用函数来创建一个子进程来执行我们指令所对应的可执行文件。
想必我们刚才上文所说的我们指令的执行过程你已经很熟悉了,但是我们回看我们指令执行的过程,我们也许会有一个疑惑的点,那就是当我们用户输入一行指令的时候,那么我们命令行解释器获取完指令回到特定的路径下去搜索匹配,那么这里我们可能会产生一个疑问,那么就是我们用户自己输入的各个不同的指令,命令行解释器怎么知道该指令所对应的可执行文件具体在哪个位置,以及它究竟该在哪里去进行搜索?那么我们知道这些指令所对应的可执行文件是存放在我们的系统的特定路径下,也就是配置文件目录下,那么我们命令行解释器如果能够成功搜索匹配到对应的可执行文件,那么它一定得记住我们这些指令所在的可执行文件可能会出现在哪些位置,然后就到这些路径下依次去搜索就可以了。
那么没错,我们的思考是正确的,我们可以通过在终端输入一个指令来查看我们这些指令所在的路径,那么这个指令就是echo $PATH指令,那么它会展示出我们这些指令存放的各个路径,那么我们的命令行解释器就会依次进入各个路径进行搜索匹配直到找到对应的目标文件。

那么我们知道我们命令行解释器之所以能够获取到我们输入指令所在的可执行文件,会因为它本身有我们这些指令保存的各个不同的路径,从而只需要到这些路径中去依次进行搜索匹配即可,所以这就解释了,我们如果在终端自己随便输入一个不存在的指令,那么当命令行解释器搜寻完所有的配置文件之后,都查不到我们该指令的内容,那么它就会在终端打印我们的command not found,所以今天我们弄清楚命令行解释器执行我们指令的原理之后,我们知道它手上是有一个指令可能出现的所有位置的记录,那么我们如果要自己自定义一个指令,比如我们用c语言编写了一个mycommand的可执行文件,那么如果我们要想达到输入mycommand,那么我们的命令行解释器能够执行我们编译好的mycommand的可执行文件,那么我们就有两种策略:
第一种是我们将我们该可执行文件放到系统的配置文件目录中,因为我们知道我们命令行解释器会到这些路径下搜索,一旦找到,那么就会创建一个子进程来进行执行
第二种就是我们将我们该可执行文件所在的目录添加到我们的命令行解释器要进行指令的搜索路径当中,那么它也会从该目录下找到我们该文件然后执行,但是需要我们输入指令来export PATH=$PATH:/home/path添加。

2.环境变量
那么刚才所介绍这个指令的搜索路径我们这个信息也只是在我们环境变量中的冰山一角,那么铺垫了这么久,我们来正式介绍我们的环境变量,那么我们先回答我们环境变量是什么:
那么我们环境变量则是记录了我们当前进程的运行环境的信息。
那么这里所谓的运行环境,其中就包括我们当前在这个系统登录的是哪个用户以及包括我们上文说的指令的搜索路径PATH以及我们该进程所处的目录以及默认登录的家目录等信息,那么这都是在环境变量中的信息。
那么看到这,你可能会有一个疑问,那么就是我们记录一个进程的环境变量,那么至于记录这么多信息吗,那么我们进程运行不就操作系统对该进程创建一个task_struct结构体然后把它的内核数据加载到内存不就可以了吗,需要用到这么多信息吗?
那么对此我想说的是,环境变量之所以设计这些肯定有它的道理,比如我们环境变量会有当前登录的用户的信息,你看似这个好像跟进程的运行没有关系,但是我们知道我们在Linux操作系统有权限的问题,那么假如我们在我们该进程的代码里有向其他文件进行读取或者写入的操作,那么我们能不能进行读取或者写入,那么这就和用户所具有的权限有关,那么我们需要知道用户是谁以及对应的身份才能允许确定能不能执行该操作,所以我们要知道进程中没有用到某些环境变量里面的内容不代表它没有用。
那么我们了解到环境变量就是记录了进程运行有关的运行环境信息,那么我们可以用我们的env指令来查看我们的环境变量

那么知道了环境变量的概念之后,那么我们再来谈一下环境变量的特征,那么环境变量的第一个特征就是全局性,那么为什么这么说呢,那么我们知道我们没创建一个进程,那么我们该进程都会有一份对应的task_struct结构体以及对应的一份环境变量,那么我们task_struct结构体的也有一个字段envp来保存环境变量的地址。
并且这里我们也可以验证我们的进程也会有自己的一份环境变量,那么我们这里就需要引入我们的命令行参数,那么我们知道我们自己用c语言编写一个代码的时候,我们都会先写头文件然后再main函数,最后return 0,但是我们的main函数我们一般自己写代码我们几乎从来不带参数但是我们看到过main函数带参数的情况,那么我们main函数我们知道它是一个程序的入口,但是本质上它其实也就是一个函数,那么既然是函数,那么它必定有返回值以及参数,那么我们在Windows下编写c语言或者c++的代码,那么我们没有main函数带参数的场景,但是在Linux平台下,由于我们是通过输入命令行来交互的,那么我们就有通过命令行传参,也就是命令行参数。
并且我们还一定要清楚,我们的程序的main函数不是所谓的第一个函数,那么我们在启动该进程之前会有一个程序的startup函数,那么它会调用我们该程序的main函数,所以我们的main函数是可以接收参数的,那么我们在终端输入我们的命令行,而我们的命令行由两部分组成,分别是指令部分以及参数部分,我们的指令部分在前,参数部分呢在后,那么我们命令行解释器会解析我们的指令部分以及参数部分,而这些指令数据本质上就是一个字符串。
那么我们main函数的参数列表有两种,第一种就是int main(int argc,char* argv[])


那么第一个参数就是指令的个数包括指令部分以及参数部分,比如ls -l,会被解析为“ls”和“-l”两部分,那么指令个数就是2,argc就是2,然后我们这两个字符串就会被保存到我们的指针数组里,也称之为参数列表里,那么我们当用c语言编写好一个mycode的函数,那么意味着我们可以向mycode进程传参,那么我们接下来也可以编写一个c语言代码来验证一下:
那么如图可以看到结果,但是这还跟我们想要看到的环境变量还没有联系,那么刚才只是铺垫,那么我们的main函数的参数列表除了刚才的那种形式,在我们的Linux平台还有第二种形式:
int main(int argc ,char* argv[],char* env[])
也就是说还有第三个参数,那么这第三个参数也是一个指针数组,那么看这个指针数组的名字你也知道了,那么这个指针数组就是我们的环境变量,那么没错我们不仅可以向我们的main函数传递我们的命令行参数还可以传递我们的环境变量,那么我们这个env函数的最后一个元素是以NULL结尾的,那么我们可以遍历我们的env数组来查看我们该进程的环境变量了,并且我们还可以有系统调用接口,getenv函数来得到特定属性的环境变量

那么这个char* env的存在就证明了,我们每一个进程都有自己的环境变量,而我们进程具体是怎么得到自己的环境变量,那么我们知道我们可以通过命令行传参的方式得到。
但是我们发现我们自己在Linux平台上自己写代码,我们的main函数是不加任何参数,那么我们运行这个程序也就相当于创建了一个进程,但是我们创建了一个进程也就意味着创建了对应的一份task_struct结构体以及自己的对应的一份环境变量,那么我们这里没有定义参数,那么我们这里进程是怎么生成自己一份的环境变量呢?
那么我们子进程的环境变量是继承于我们父进程的,并且修改了其中的部分属性,就像我们用fork函数创建子进程一样,那么我们子进程的task_struct结构体也是直接拷贝一份父进程的task_struct结构体然后修改其中的部分属性包括进程编号以及状态等,所以我们不必直接传参,那么在我们操作系统内核会帮组我们再创建子进程的时候,拷贝我们父进程的环境变量并且修改部分属性,所以我们说我们的环境变量具有全局性。
3.结语
那么这就是本篇关于环境变量的全部内容了,那么本篇文章围绕着环境变量讲述了环境变量是什么,有什么用,以及一些相关的指令,那么我的下一篇文章将是讲解我们的进程地址空间,我会持续更新,希望你能多多关注,希望本篇文章能够让你有所收获。

相关文章:
深入Linux系列之环境变量
深入Linux系列之环境变量 那么在之前的内容中,我们已经介绍了我们Linux进程的一些关键属性,例如进程编号以及进程状态和进程优先级,那么本篇文章接介绍Linux的环境变量这一知识点,那么废话不多说,我们进入环境变量的讲…...
国产编辑器EverEdit - Web预览功能
1 Web预览 1.1 应用场景 在编辑HTML文件时,可以通过EverEdit的Web预览功能,方便用户随时观察和调整HTML代码。 1.2 使用方法 1.2.1 使用EverEdit内部浏览器预览 选择主菜单查看 -> Web预览,或使用快捷键Ctrl B,即可打开Ev…...
C#中的Frm_Welcome.Instance.Show(),是什么意思
Frm_Welcome.Instance.Show() 是一种常见的单例模式(Singleton Pattern)实现方式,通常用于在应用程序中确保某个窗体(Form)只有一个实例,并通过该实例显示窗体。以下是对这段代码的详细解释: 代…...
07苍穹外卖之redis缓存商品、购物车(redis案例缓存实现)
课程内容 缓存菜品 缓存套餐 添加购物车 查看购物车 清空购物车 功能实现:缓存商品、购物车 效果图: 1. 缓存菜品 1.1 问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压…...
C++开发(软件开发)常见面试题
目录 1、C里指针和数组的区别 2、C中空指针请使用nullptr不要使用NULL 3、http/https区别和头部结构? 4、有了mac地址为什么还要ip地址?ip地址的作用 5、有了路由器为什么还要交换机? 6、面向对象三大特性 7、友元函数 8、大端小端 …...
人工智能-A*算法与卷积神经网络(CNN)结合实现路径规划
以下是一个将 A* 算法与卷积神经网络(CNN)结合实现路径规划的代码示例。主要思路是使用 A* 算法生成训练数据,然后用这些数据训练一个 CNN 模型,让 CNN 学习如何预测路径,最后使用训练好的 CNN 模型进行路径规划。 代码实现 import numpy as np import heapq import tor…...
蓝桥杯备赛——进制转化相关问题
目录 一、基础概念 二、问题研究(1) 代码解读: 1. transfer 函数 代码功能概述 详细步骤 2. main 函数 代码功能概述 详细步骤 三、运用递归解决 (一) 代码如下: 代码解读: &#…...
DevOps的个人学习
一、DevOps介绍 软件开发最初是由两个团队组成: 开发团队:负责设计和构建系统。运维团队:负责测试代码后部署上线,确保系统稳定安全运行。 这两个看似目标不同的团队需要协同完成一个软件的开发。DevOps整合了开发与运维团队&a…...
使用Pytorch训练一个图像分类器
一、准备数据集 一般来说,当你不得不与图像、文本或者视频资料打交道时,会选择使用python的标准库将原始数据加载转化成numpy数组,甚至可以继续转换成torch.*Tensor。 对图片而言,可以使用Pillow库和OpenCV库对视频而言…...
《ARM64体系结构编程与实践》学习笔记(四)
MMU内存管理 1.MMU内存管理(armv8.6手册的D5章节),MMU包含快表TLB,TLB是对页表的部分缓存,页表是存放在内存里面的。 AArch64仅仅支持Long Descriptor的页表格式,AArch32支持两种页表格式Armv7-A Short De…...
01-SDRAM控制器的设计——案例总概述
本教程重点▷▷▷ 存储器简介。 介绍 SDRAM 的工作原理。 详细讲解SDRAM 控制的Verilog 实现方法。 PLL IP和FIFO IP 的调用,计数器设计,按键边沿捕获,数码管控制。 完成SDRAM控制器应用的完整案例。 Signal Tap 调试方法。 准备工作▷…...
京准:NTP卫星时钟服务器对于DeepSeek安全的重要性
京准:NTP卫星时钟服务器对于DeepSeek安全的重要性 京准:NTP卫星时钟服务器对于DeepSeek安全的重要性 在网络安全领域,分布式拒绝服务(DDoS)攻击一直是企业和网络服务商面临的重大威胁之一。随着攻击技术的不断演化…...
uniapp访问django目录中的图片和视频,2025[最新]中间件访问方式
新建中间件, middleware.py 匹配,以/cover_image/ 开头的图片 匹配以/episode_video/ 开头的视频 imageSrc: http://192.168.110.148:8000/cover_image/12345/1738760890657_mmexport1738154397386.jpg, videoSrc: http://192.168.110.148:8000/episode_video/12345/compres…...
RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决
RuoYi-Vue-Oracle的oracle driver驱动配置问题ojdbc8-12.2.0.1.jar的解决 1、报错情况 下载:https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle 用idea打开,启动: 日志有报错: 点右侧m图标,maven有以下报误 &…...
python脚本实现windows电脑内存监控内存清理(类似rammap清空工作集功能)
import ctypes import psutil import time import sys import os from datetime import datetime import pyautogui# 检查管理员权限 def is_admin():try:return ctypes.windll.shell32.IsUserAnAdmin()except:return False# 内存清理核心功能 def cleanup_memory(aggressivene…...
【狂热算法篇】并查集:探秘图论中的 “连通神器”,解锁动态连通性的神秘力量
嘿,朋友们!喜欢这个并查集的讲解吗 记得点个关注哦,让我们一起探索算法的奥秘,别忘了一键三连,你的支持是我最大的动力! 欢迎拜访:羑悻的小杀马特.-CSDN博客 本篇主题:深度剖析并查…...
SpringBoot中实现动态数据源切换
SpringBoot中实现动态数据源切换 文章目录 SpringBoot中实现动态数据源切换SpringBoot中实现动态数据源切换基础知识1. 什么是数据源?2. 动态数据源切换的概念3. Spring Boot 中的默认数据源配置4. 动态数据源的挑战5. Spring 中的数据源切换方式 设计思路1. 明确应…...
数据结构及排序算法
数据结构 线性结构 ◆线性结构:每个元素最多只有一个出度和一个入度,表现为一条线状。线性表按存储方式分为顺序表和链表。 存储结构: ◆顺序存储:用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素物理上也相邻。 ◆链式存储:存储各数据元素的结点…...
Python基础-元组tuple的学习
在 Python 中,元组(tuple)是一种不可变的序列类型,允许存储不同类型的元素。元组非常类似于列表(list),但与列表不同的是,元组一旦创建,就不能修改其内容。 1 元组的创建…...
【手写公式识别】MEMix: Improving HMER with Diverse Formula Structure Augmentation 论文阅读
发表于:ICME 2024 原文链接:https://ieeexplore.ieee.org/document/10687521 源码:无 Abstract 手写数学表达式识别(HMER)旨在将数学表达式(MEs)的图像转换为相应的LaTeX序列。然而࿰…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
