环境变量与本地变量(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 架构,在超大规模的预训练数据上进行训练得到。预训练数据类型多样,覆盖广泛,包括大量网络文本、专业书籍、代码等。同时,在预训练模型的基础之上&…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...