环境变量与本地变量(Linux)
引言
在当今的计算机技术领域,Linux操作系统以其稳定性和灵活性而广受欢迎。它不仅是服务器和开发者的首选平台,也是探索计算机科学和系统编程的宝库。在这个强大的操作系统中,环境变量与本地变量扮演着至关重要的角色,它们是管理配置、传递数据和影响程序行为的关键机制。本文将引导我们深入探讨Linux中的这两种变量,理解它们的定义、用途、区别以及如何在日常工作和脚本编程中有效地利用它们。通过掌握环境变量与本地变量的知识,我们将能够更加高效地与Linux系统交互,优化我们的工作流程,并解锁系统管理的更多可能性。
并行与并发
在学习环境变量之前,我们需要有一些提前储备的知识,本文将通过并行与并发的介绍导入这些知识
并行:多个进程在多个CPU下同时运行,称之为并行。
并发:多个进程在一个CPU下采用进程切换的方式,在一个时间段内,让多个进程得以推进,称之为并发。
并发是何如切换进程的呢?
在task_struct结构中,存在时间片的概念,通过时间片与基于时间片的轮转调度算法,实现进程的切换。
寄存器
会什么函数的返回值会在函数外部拿到呢?
我们都知道,函数的返回值是一个在函数栈内的数据,当栈帧销毁,返回值便被销毁。因此需要一个不被销毁的中介去完成返回。这个中介就是寄存器。cpu内部存在大量的寄存器。

系统如何得知我们执行到那一行代码了呢?
cpu内部存在一个称为eip的寄存器。


寄存器主要分为三种种类:
通用寄存器:eax ebx ecx edx
栈帧相关的寄存器:esp ebp eip
状态相关的寄存器:status
寄存器扮演的主要功能就是:提高效率,进程高频数据放入寄存器中。cpu内的寄存器存储的是进程相关的数据(如eip)。
进程的上下文
cpu寄存器是内存级别的存储,保存的是进程的临时数据,称作进程的上下文。
进程的上下文(Process Context)是操作系统中的一个概念,它指的是在操作系统中,一个进程在执行时所需的所有信息。
这些信息包括进程的状态、程序计数器、寄存器、堆栈、内存分配、打开的文件描述符、环境变量、信号处理程序等。进程上下文是操作系统管理进程执行和切换的关键部分。
以下是进程上下文的主要组成部分和特点:
上下文切换的性能直接影响到系统的响应速度和吞吐量。


进程的切换执行:时间片到了---保存上下文---去另一个队列排队--恢复上下文---重新执行该进程
-
用户空间上下文:
- 程序计数器:指示下一条要执行的指令。
- 寄存器:包括通用寄存器、状态寄存器、指令寄存器等,它们保存了进程执行时的临时数据。
- 堆栈:包含了局部变量、函数调用的返回地址、参数等信息。
- 用户空间的内存:包括进程的代码段、数据段、堆和栈。
-
内核空间上下文:
- 进程控制块(PCB):也称为任务结构,包含了进程的ID、状态、优先级、父进程ID、子进程列表、资源使用情况等。
- 文件描述符表:记录了进程打开的所有文件描述符及其对应的文件表项。
- 虚拟内存表:包括页表、段表等,用于虚拟内存到物理内存的映射。
- 信号处理程序:定义了进程如何响应接收到的信号。
-
上下文切换:
- 当操作系统进行进程调度时,它会执行上下文切换,即保存当前运行进程的上下文,并加载下一个将要运行进程的上下文。
- 上下文切换包括保存当前进程的状态和恢复另一个进程的状态,这是一个相对昂贵的操作,因为它涉及到CPU寄存器的保存和恢复,以及内存管理单元(MMU)的更新。
-
上下文的状态:
- 运行态:进程正在CPU上执行。
- 就绪态:进程已准备好执行,但由于CPU被其他进程占用而等待。
- 阻塞态:进程因等待某些事件(如I/O操作完成)而暂时停止执行。
环境变量
环境变量这部分我们将通过两部分进行介绍1.见见猪跑(简单认识一下) 2.尝尝猪肉(了解具体信息)
见见猪跑
1.环境变量PATH
为什么ls等系统指令可以直接执行,但是我们的可执行程序,需要指明执行的目录呢?


我们都知道ls这种指令是/usr/bin下的可执行程序,那bash为什么知道默认去这个目录找指令呢?

这其实与PATH这个环境变量有关,PATH这个环境变量记录了指令目录信息。

发现PATH环境变是用冒号作为分隔符,定义出来的很多路径。
因此只有当你的程序在这些路径下,bash才能找到这个程序,否则就需要指定目录。
当执行ls时,会在这些被冒号分割的路径下一个一个的去查找。
将自己的指令添加到环境变量
不可以有空格 不可以直接写=./(这种是覆盖写入) 不要用相对路径./(路径改变将失效 )


这样t1在PATH中存在之后,就可以直接执行t1了。which用来PATH中指令的路径。
当然,这种修改是内存级的(本地变量的配置也是内存级别的),当重新进入shell中,PATH将恢复初始水平。
PATH等环境变量是shell启动时配置的。
2.环境变量HOME

登陆时,用你的用户名去配置$HOME,这就是你的家目录
3.SHELL

bash命令行就是当前的shell环境。
4.env指令(environment):查看环境变量

env展现的这一大坨就是shell中所有的环境变量。涵盖了一些基础的信息。
![]()
已知shell可以记忆历史指令
history指令可以记忆最近的1000条指令,这个1000就是由HISTSIZE控制的。
终端信息,这是默认的终端设备文件

ls的配色方案

USER:记录用户
![]()
PWD:会记录当前的路径
OLDPWD:对应cd -

尝尝猪肉
通过上述的介绍,可以了解到:环境变量其实是一个KV模型,键值对应着特殊的val
getenv函数
除了通过env可以得到对应的环境变量,getenv这个函数也可以得到环境变量。
头文件在stdlib.h中

由于环境变量是一个KV模型,所以给定K值,可以得到对应的V。


传入环境变量的名称(字符串),可以得到对应的val(字符串)

需要注意的是,字符和指针(字符串在这个地方被理解为首字符的地址)不能直接比较(string重载的operator==,只能用来比较整个string对象!!!string本身封装过的一个字符串,存储的是char,而不是字符串)


因此代码应该修改为strcmp

c_str可以得到C++string的C接口对象。

现在我们就可以对环境变量完成KV类型的调用。

命令行参数与main函数参数
其实main函数是可以带参数的
1.双参数

参数有两个时,参数是一个整型和一个指针数组,argc(c就是count),argv内部有多少元素由argc决定。
linux需要经常用这两个东西,这些东西是用来接收命令行指令中的信息的。

可以看到命令行指令可以携带参数

我们输入的 ./t1 -a -b -c 其实会以空格为分隔符,被解析为一个个字符串
“./t1”
“ -a ”
“-b ”
“-c”
这叫做指令的解析。
有几个字符串,就初始化argc为几。


如:ls -l ls -a
这种指针数组被称为向量表
当然main函数还可以继续喂参数

env这个指针数组存储的就是环境变量。
env[]类似于argv[],argv[i]当执行结束时,下一个元素被设置为NULL。

打印下看看内部是什么东西

发现打印的环境中的环境变量 。因此我们可以通过env[]直接获得环境变量。

环境变量的全局属性
![]()
通过新增环境变量去继承
在命令行直接定义的变量成为本地变量
转变为环境变量export导出
![]()


发现环境变量被继承。
取消环境变量:unset
unset直接跟上环境变量即可,不需要$

unset 命令可以用来取消环境变量和本地变量。
本地变量

不通过export导入的变量就是本地变量(内存级别)

打印本地变量同样需要$符号,否则会被认为是字符串。
查询:set
set可以用来查询本地变量+环境变量。本地变量不会被子进程继承。bash的环境变量只会在bash内部

内建指令
明明本地变量不能被继承,为什么echo作为bash的子进程,可以打印本地变量

其实需要指明一个点:并不是所有指令都是bash的子进程。这种指令称作内建指令。
内建指令是bash本身的一个功能,不需要通过子进程实现。

cd就是一个典型的内建指令
当你在shell中输入cd /some/directory时,shell不会去文件系统中查找名为cd的可执行文件,而是直接执行内建的cd逻辑,将当前工作目录更改为指定的路径。
cd的执行不会导致shell进程的创建或终止,因为它是shell自身的一部分。
由于cd是内建的,它可以直接访问和修改shell的内部变量,如PWD(当前工作目录的路径)。
cd可以直接访问shell的本地变量(如果变量包含一个有效的路径),只要正确地引用变量值即可。
例如:
MYDIR="/home/user/documents"
要使用cd命令改变到这个变量指定的目录,你可以这样做:
cd "$MYDIR"
在这里,双引号"是用来确保变量$MYDIR的值被正确地作为单个字符串传递给cd命令。如果路径中包含空格或者特殊字符,使用双引号是特别重要的,因为它可以防止这些字符被错误地解释为多个参数或者命令。
如果不使用双引号,并且路径中包含空格,那么cd命令可能会无法正确解析路径,从而导致错误。例如:
MYDIR="/home/user/my documents"
cd $MYDIR # 这可能会导致错误,因为路径被分解为多个参数(#是shell的注释符号)
在上面的例子中,cd会尝试改变到名为/home/user/my的目录,然后尝试执行名为documents的命令,这显然不是我们想要的结果。
/*
题外话:
Xshell会提供一种shell环境,所有的shell环境都是将#作为注释符号
shell的规范是统一的吗?
Shell的规范并不是完全统一的,因为存在多种不同的shell,每种shell都有自己的特点和规范。虽然许多shell在基本语法和功能上有所共通,但它们在特定功能、扩展、内置命令以及脚本编程能力等方面存在差异。
以下是一些常见的shell及其特点:
Bash (Bourne Again SHell):
最广泛使用的shell之一,是许多Linux发行版的默认shell。
它遵循POSIX标准,但也包含了许多扩展。
Bash脚本通常以 #!/bin/bash 开头。
SH (Bourne SHell):
最初的Unix shell,由Steve Bourne编写。
它是许多其他shell的基础。
SH脚本通常以 #!/bin/sh 开头。
CSH (C SHell):
受C语言影响较深,语法类似于C。
它不是Bourne shell家族的一部分,因此其脚本语法与Bash和SH不同。
CSH脚本通常以 #!/bin/csh 开头。
TCSH:
是CSH的一个扩展版本,提供了一些额外的功能和改进。
TCSH脚本通常以 #!/bin/tcsh 开头。
ZSH (Z SHell):
提供了强大的命令行编辑、拼写纠正、文件名补全等功能。
它具有高度的可配置性。
ZSH脚本通常以 #!/bin/zsh 开头。
尽管不同shell之间存在差异,POSIX标准定义了shell应该遵循的一组基本规范,以确保在符合POSIX的系统中,基本的shell脚本可以在不同的shell上运行。POSIX标准旨在提供跨平台的兼容性,因此大多数shell都遵循POSIX的基本规则,包括使用 # 作为注释符号、基本的控制结构(如if、for、while等)。
然而,超出POSIX标准的特性,如Bash中的某些数组操作或高级参数扩展,可能在其他shell中不可用或不兼容。因此,编写跨shell兼容的脚本时,通常需要限制使用POSIX标准中定义的功能。
*/
cd的模拟
如果是这是一个bash的话,那么cd并不会创建子进程(fork),而是直接更改地址
# 指令被拆解的字符串的地址会存放在argv这个指针数组中
chdir接口
chdir可以将程序进程的地址更改到指定的地址

cd模拟实现
如果argv[0]解析到字符串为cd时,将不创建子进程,直接将进程的地址修改为cd后面带着的地址:argv[1]
argv[i]就是我们输入的指令解析的字符串

环境变量的其他获取方式:C语言提供的第三方变量
environ是一个二级指针,指向环境变量表,这是C语言提供的第三方变量。
可以实现不给main函数传参,就能使用环境变量。



(数组名是数组首元素(一级指针)的地址(二级指针),所以二级指针解引用就可以得到一级指针:即一个字符串的首字符地址)
有字符串首字符的地址,就可以打印一个字符串
题外话
extern的作用
在C语言中,`extern`关键字主要有以下作用:
1. **跨文件变量和函数引用**:`extern`关键字用于在一个文件中引用另一个文件中定义的变量或函数。这允许在不同文件之间共享全局变量和函数。例如,如果在文件A中定义了一个变量或函数,在文件B中可以通过声明`extern`来引用这个变量或函数。
2. **变量和函数声明**:使用`extern`关键字可以声明一个变量或函数,表明其定义在其他地方。这通常用于在函数外部声明变量,使得它们可以在不同的文件中被访问。需要注意的是,`extern`声明并不分配内存,它只是告诉编译器该变量或函数在其他地方定义。
3. **避免重复定义**:在多文件编程中,如果不希望在其他文件中引用某个文件中的变量,可以在该变量前加上`static`关键字。而使用`extern`则意味着变量可以被其他文件引用,从而避免了重复定义的问题。
以下是一些具体的用法示例:
- **引用同一文件中的变量**:如果想在函数中使用在后面定义的变量,可以在函数前使用`extern`来声明这个变量。
- **引用不同文件中的变量或函数**:在文件A中定义变量或函数,在文件B中使用`extern`来声明这些变量或函数,然后就可以在文件B中引用它们。
- **全局和局部变量**:全局变量(外部变量)默认具有`extern`属性,意味着它们可以被其他文件中的函数访问。局部变量则只在定义它们的函数内部有效。
总之,`extern`关键字在C语言中主要用于声明在不同文件中定义的全局变量和函数,使得这些变量和函数可以在多个文件中被共享和访问。
相关文章:
环境变量与本地变量(Linux)
引言 在当今的计算机技术领域,Linux操作系统以其稳定性和灵活性而广受欢迎。它不仅是服务器和开发者的首选平台,也是探索计算机科学和系统编程的宝库。在这个强大的操作系统中,环境变量与本地变量扮演着至关重要的角色,它们是管理…...
【完-网络安全】Windows防火墙及出入站规则
文章目录 防火墙入站和出站的区别域网络、专用网络、公用网络的区别 防火墙 防火墙默认状态一般是出站允许,入站阻止。 入站和出站的区别 入站就是别人来访问我们的主机,也就是正向shell的操作 出站就是反向shell,主机需要主动连接kali&am…...
Vue学习记录之十七 css中样式穿透及新特征介绍
一、scoped原理 在vue页面的css中,有一个设置为scoped,使用以后dom的节点会出现下面的规则。其实我们打完包就是一个html页面,如果不做处理,将会导致css混乱。 给HTML的DOM节点加一个不重复data属性(形如:data-v-123)来表示他的唯一性在每句css选择器的末尾(编译后的生成的…...
Nature 正刊丨海洋涡旋中常见的地下热浪和寒潮
01摘要 由于全球变暖,极端海洋温度事件变得越来越普遍,造成了灾难性的生态和社会经济影响1,2,3,4,5。尽管基于卫星观测对表层海洋热浪(MHW)和海洋寒潮(MCS)进行了广泛的研究6,7,但我们对这些极…...
代码随想录算法训练营第六十二天| prim算法,kruskal算法
训练营六十二天打卡,图论比较难,坚持下来胜利就在眼前! 53.卡码网【寻宝】 题目链接 解题过程 没做过类似的题目,跟着答案敲了一遍最小生成树 可以使用 prim算法 也可以使用 kruskal算法计算出来。prim算法 是从节点的角度 采用…...
Newstar_week1_week2_wp
week1 wp crypto 一眼秒了 n费马分解再rsa flag: import libnum import gmpy2 from Crypto.Util.number import * p 9648423029010515676590551740010426534945737639235739800643989352039852507298491399561035009163427050370107570733633350911691280297…...
今天我们研究一段代码(异或位运算)
let a 18 // 甲 let b 20 // 乙a a ^ b b a ^ b a a ^ b console.log("a",a) // a 20 console.log("b",b) // b 18今天我们就研究上面这一段代码,简单解释一下,初始化一个a 18 b 20, 中间经过了三次的异或之后…...
pycharm中使用ctrl+鼠标滚轮改变字体大小
文章目录 pycharm使用ctrl鼠标滚轮改变字体大小1.打开pycharm选择file2.选择setting4.选择keymap,然后再右边的输入框中输入increase进行增大字体4.鼠标选择后,点击添加鼠标快捷方式,然后设置鼠标滚轮往上增大字体。5.设置缩小字体࿰…...
【算法-动态规划】打家劫舍专题
文章目录 1.打家劫舍1.1一维数组1.2三变量法1.3双数组法 2.打家劫舍22.1双数组法2.2 三变量法 3.打家劫舍33.1动态规划3.2双变量法 4.删除相邻数字的最大分数4.1双状态数组4.2一维数组4.3三变量法 1.打家劫舍 198. 打家劫舍 - 力扣(LeetCode) 1.1一维数…...
关于技术管理者的一些思考
前 言 在软件开发领域,当一名资深工程师有机会成为一名技术管理者的时候,通常他/她的反应是什么?兴奋、担扰、无奈还是推托,具体是什么心情也许对结果并不重要,更加重要是在一刻,我们一定要问问我们内心的…...
Alpha-CLIP: A CLIP Model Focusing on Wherever You Want CVPR 2024
在原始的接受RGB三通道输入的CLIP模型的上额外增加了一个alpha通道。在千万量级的RGBA-region的图像文本对上进行训练后,Alpha-CLIP可以在保证CLIP原始感知能力的前提下,关注到任意指定区域。 GitHub - SunzeY/AlphaCLIP: [CVPR 2024] Alpha-CLIP: A CLI…...
Golang | Leetcode Golang题解之第495题提莫攻击
题目: 题解: func findPoisonedDuration(timeSeries []int, duration int) (ans int) {expired : 0for _, t : range timeSeries {if t > expired {ans duration} else {ans t duration - expired}expired t duration}return }...
04 go语言(golang) - 变量和赋值过程
变量 在Go语言中,变量的定义和初始化是编程的基础部分。Go提供了多种方式来声明和初始化变量,以适应不同的使用场景。 基本变量声明 使用var关键字: 使用var关键字可以在函数内部或外部声明变量。如果在函数外部声明,该变量为全…...
语言/图像/视频模型一网打尽!BigModel大模型开放平台助力开发者轻松打造AI新应用!
2024年8⽉28⽇,在ACM SIGKDD(国际数据挖掘与知识发现⼤会,KDD)上会议现场,智谱AI重磅推出了新⼀代全⾃研基座⼤模型 GLM-4-Plus、图像/视频理解模型 GLM-4V-Plus 和⽂⽣图模型 CogView3-Plus。这些新模型,已…...
Go语言Linux环境搭建以编写第一个Go程序
目录 文章目录 目录Go语言入门1、说明2、CentOS7安装Go3、编写第一个程序3.1、编写程序3.2、运行程序3.3、生成二进制文件4、编写第一个web程序4.1、编写代码4.2、运行程序4.3、测试访问4.4、生成二进制配置Vim-go语法高亮1)、下载和设置Vundle.vim(vim安装插件的工具)2)、…...
使用 Go 构建一个最小的 API 应用
最近有项目要使用 Go 开发,作为一个. NET Core 选手,准备先撸一个包含 CRUD 的最小 MVP 项目练手。 要创建一个 TODO 应用,会创建下面这些接口: APIDescriptionRequest bodyResponse bodyGET /todoitemsGet all to-do itemsNone…...
MySQL 日常维护指南:常见任务、频率及问题解决
MySQL 作为一种广泛使用的开源关系型数据库,随着数据量和应用复杂性的增加,定期的数据库维护对于保持系统高效运行至关重要。通过合理的日常维护,数据库管理员能够确保 MySQL 数据库的稳定性、性能以及数据的完整性。本文将介绍 MySQL 的常见…...
oracle ORA-24920:列大小对于客户机过大
问题描述 在一次读取某个视图数据过程中,当数据读取到x条时,报错ORA-24920:列大小对于客户机过大。 通过查询资料得知,oracle 数据库升级到了12c,VARCHAR2的容量也从4000升级到了32767。 所以猜测某个字段的长度超过4…...
使用 Docker compose 部署 Nacos(达梦数据库)
1. 制作镜像的源码地址 https://github.com/wangsilingwsl/nacos-dm.git 参考的开源项目:https://github.com/jeecgboot/JeecgBoot/tree/master/jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos (master分支;tag:v3.7.1&#…...
人工智能 | 阿里通义千问大模型
简介 通义千问系列模型为阿里云研发的大语言模型。千问模型基于 Transformer 架构,在超大规模的预训练数据上进行训练得到。预训练数据类型多样,覆盖广泛,包括大量网络文本、专业书籍、代码等。同时,在预训练模型的基础之上&…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Unity UGUI Button事件流程
场景结构 测试代码 public class TestBtn : MonoBehaviour {void Start(){var btn GetComponent<Button>();btn.onClick.AddListener(OnClick);}private void OnClick(){Debug.Log("666");}}当添加事件时 // 实例化一个ButtonClickedEvent的事件 [Formerl…...
rm视觉学习1-自瞄部分
首先先感谢中南大学的开源,提供了很全面的思路,减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接:https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架: 代码框架结构:readme有…...
医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...
【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...
