【Linux】第十五站:环境变量

news2024/11/24 15:32:00

文章目录

  • 一、进程相关的一些概念
    • 1.一些常见的概念
    • 2.对于并发
    • 3.**进程切换**
  • 二、环境变量
    • 1.PATH环境变量
    • 2.HOME环境变量
    • 3.SHELL环境变量
    • 4.env
    • 5.系统调用接口与环境变量
    • 6.什么是环境变量?
    • 7.命令行参数
    • 8.main函数的第三个命令行参数
    • 9.如何验证环境变量是可以被继承的
    • 10.本地变量与内建命令

一、进程相关的一些概念

1.一些常见的概念

  • 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
  • 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  • 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行(每个CPU都有Linux内核的O(1)调度算法)
  • 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发 。

2.对于并发

如下图所示,当多个进程在CPU上执行的的时候,CPU会让他们不断的切换,但是由于CPU的速度太快,所以我们看上去好像就是没有任何的影响

在进程切换的时候,会有一个时间片,如果在这个时间段内没有跑完这个进程,那么就先让他下去,让其他进程先跑。所以这样可以避免一个进程把CPU给卡死。这就是基于进程切换基于时间片轮转的调度算法

我们也在前面提到过,CPU会维护两个队列。当一个进程的时间片过了以后,会将这个进程从CPU上剥离下来

剥离下来以后,会让这个被剥离出来的进程去另外一个队列中排队。这样的话,防止还在原队列中排队,却由于优先级的太高的问题又让他先执行了。

必须得先等原来的一个进程队列给跑完,才能继续跑。

这也就是为什么要两个队列的原因。

3.进程切换

  1. 为什么函数返回值,会被外部拿到呢?

    在我们返回的时候

    比如return a其实就是mov eax 10,将10放到eax这个寄存器中

    像我们写的这个int a = add(10,20)

    其实就是将这个返回值写入eax寄存器中,这个等号会被编译为一些mov指令,然后mov指令将寄存器的值放入a中。

    所以是通过CPU寄存器返回的。

    像我们之前数据结构返回的时候,不是返回一个结点的,而是返回一个指针,就是因为结点太大了。

  2. 系统如何得知我们的进程当前执行到哪行代码了?

    程序计数器PC,eip:会记录当前进程正在执行指令的下一行指令的地址!

    通过这个程序计数器就可以很容易的找到当前执行到哪行代码了。

    实际上我们的寄存器大概分为以下几类

    • 通用寄存器:eax,ebx,ecx,edx
    • 栈帧:ebp,esp,eip
    • 状态寄存器:status

    总之寄存器很多

    那么这个寄存器扮演什么样的角色呢?

    寄存器也具有数据的临时保存能力,注定了当前的计算机在运行时候,重要的数据必须放在CPU内部,因为离CPU越近,存取的效率越高。单纯从硬件来考虑,CPU寄存器的数据放在哪里都可以。但是离的越近,效率越高。

    所以主要目的还是提高效率,将进程的高频数据放入寄存器中。

    CPU内的寄存器里面保存的是进程相关的数据

    这些进程相关的数据是随时可以被访问或者被修改的

    所以:CPU寄存器里面保存的是进程的临时数据-----这些数据我们称为进程的上下文数据

  3. 如何切换

    进程在CPU上离开的时候,要将自己的上下文数据保存好,甚至带走

    而保存的目的,未来都是为了恢复。

    所以进程在被切换的时候,要做下面两件事

    1. 保存上下文
    2. 恢复上下文

    那么如何保存呢?

    我们可以定义一个结构体

    struct reg_info
    {
    	int eax;
    	int ebx;
    	int eip;
    	//....
    }
    

    然后将这个结构体套入到PCB结构体里面

    也就是说将数据放入到PCB中

    不过上面这种做法是可以,但是linux中实际并不是这么做的,因为这样太慢了

二、环境变量

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
  • 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性

1.PATH环境变量

如下所示,我们先简单的写一段代码

image-20231110210016347

然后当我们运行的时候,我们知道,像我们自己写的程序是需要带上./的,而系统中的那些指令却不需要

image-20231110210155960

我们也知道,像系统这些命令都是在系统的默认指定路径下的,像这里路径的操作系统都能找到的

而像我们的命令,是不在系统的指定路径下的,所以找不到

image-20231110211008917

那么这究竟是为什么呢?都是一个目录,还分个一二三?

这一切的一切的原因:就是因为系统为我们提供了一个环境变量,这个环境变量叫做PATH

这个PATH是我们登录Xshell就天然存在的PATH

如果我们想要查看这个PATH,我们需要像下面这样做

echo $PATH

image-20231110211311555

在这里我们会看到很多路径,路径之间用:分割

有了这些路径,当我们输入指令的时候,系统便会从这些路径中按照顺序依次查找。没找到就找下一个路径。找到了就执行。而我们这个正好处于/usr/bin这个路径下,所以是可以找到的。

而我们前面的mycmd并不在这些路径,所以就找不到,就会提示找不到这个指令。

这个环境变量PATH就叫做Linux系统的指令搜索路径

这也就意味着,如果我们可以有两种做法,使得我们的程序直接输入名字就可以执行了

  1. 将该指令放到PATH的某条路径中
  2. 将我们本路径添加到PATH中

这两种方法都是可以的,第一件事我们之前做过

我们现在来做一下第二件事

我们可以这样做

PATH=$PATH:xxxx//当前目录的路径

image-20231110212447948

然后我们就可以直接执行我们的指令了

image-20231110212541234

甚至于,我们把这个程序名字一改,也是可以跑的,因为系统自动会从当前的路径进行搜索我们输入的指令

甚至于,我们的which也可以搜索到了

image-20231110212724476

注意我们不可以像下面这样做,这样会直接覆盖掉以前的环境变量的,就会造成以前绝大部分的指令都跑不了了

image-20231110213839407

不过pwd还可以跑

image-20231110213915683

就是因为以前的环境变量都被覆盖了。

那么如何恢复呢?其实我们这个环境变量是一个内存级别的,我们只需要关闭Xshell,然后重新登录即可。

也就是说,都是在shell中保存的。

2.HOME环境变量

当我们用root账号显示这个环境变量的时候,显示的是这样的

image-20231110215553046

当我们用普通账号显示的时候,是这样的

image-20231110215611089

这个环境变量也正好解释了,为什么我们一登陆的时候就是这个目录下。

主要原因,就是在我们登录时,会识别我们这个账户是谁,然后给我们填充$HOME环境变量

在登录的时候,默认就是cd $HOME

3.SHELL环境变量

这个环境变量可以让我们看到我们当前用的是哪个shell

image-20231110220255347

4.env

除了上面的这三个环境变量,其实还有很多的环境变量,那么我们如何去查找呢?我们可以使用env命令

这个可以看到,我们系统里面的所有的环境变量

image-20231110220442952

其中比如

HOSTNAME代表的就是主机名

HISTSIZE代表的是历史命令被记录下来的条数(这个主要应用于我们的指令上下翻,我们知道是可以看到我们以前输入的指令的,而这些指令最多只能保存1000条,history这条指令可以查看到我们历史的所有指令)

SSH_TTY代表的就是我们当前的终端设备文件,如下是它的用法

image-20231110221038988

USER代表的就是我们当前的账户是谁

LS_COLORS代表的是配色方案

PWD代表的就是当前进程所代表的路径(如果我们把当前路径换了,这个也会随之改变,所以我们可以取到我们当前的路径,就是因为PWD这个环境变量会记录我们当前进程所处的工作目录)

LANG是编码方案

LOGNAME指的是当前登录用户是谁

OLDPWD代表的就是进程上一次的路径(这也就是cd -这条指令可以执行原因)

其中对于USER和LOGNAME我们可以暂时理解为是一样的,因为无论是普通用户和root用户我们现在来查看起来都是一样的

image-20231111153450198

image-20231111153514233

5.系统调用接口与环境变量

我们前面的方法说明了环境变量可以通过指令去查看,可是我们未来的代码是不可能通过指令去查看环境变量的,所以就有了系统调用接口查看环境变量

man getenv

我们可以用上面这个指令去查看这些系统调用接口

image-20231111153915834

我们就可以看到这个函数了

我们可以将这个环境变量的名字给这个函数,然后这个函数就会返回这个环境变量的值

image-20231111154331033

然后我们就可以打印出环境变量了

image-20231111154351513

现在我们使用这个代码

image-20231111155957552

image-20231111160014960

而同一份代码,当我们切换到root的时候,结果也随之改变

image-20231111160303748

所以说,有了环境变量的存在,不同的账号执行同一份代码会有不同的结果。

所以我们就可以对权限有更进一步的了解了

image-20231111160844292

image-20231111160902934

image-20231111160920370

所以因为有环境变量的存在,我们系统就能认识到这个人是谁,所以就可以与文件中的拥有者,所属组进行对比。进而可以实现权限

6.什么是环境变量?

环境变量是系统提供的一组name=value形式的变量,不同的环境变量,有不同的用户,通常具有全局属性。

对于我们的系统而言,存在着环境变量,这个存在不因为进程的创建而存在,在系统启动的时候就已经有了。默认的环境变量就是被bash先获得到。

那么环境变量具有全局属性,什么是全局属性呢?

像我们前面写的程序中可以使用getenv函数来获取环境变量。

那么还有没有其他方法获取环境变量呢?

7.命令行参数

其实像C语言中的main函数是可以带参数的

int main(int argc,char* argv[])
{}

这两个参数中,arg是参数的意思,c是count的意思,代表右边数组的元素,v是vector的意思,代表一个数组。

我们使用如下代码

image-20231111163815354

运行结果为

image-20231111163910355

所以说,实际上,在执行的时候,main函数会先传参。会将参数的数据进行填充

image-20231111164057462

其实,我们的命令行中输入的其实就是一串字符串,即在bash看来就是这样的一些字符串

"./mycmd -a -b -c"

然后bash会将这个字符串打散成四个字符串,如下图所示

image-20231111165241450

将这个处理好以后,然后传给main函数

这个就是命令行的解析工作

那么为什么要这样做呢?

我们可以使用如下代码

image-20231111171153168

所以就可以产生如下效果了

image-20231111171224910

而这个不就是类似于下面这种的吗

image-20231111171258014

那么为什么要这样做呢?

这是因为这样做,可以为指令、工具、软件等提供命令行选项的支持!!

其实对于argv这个数组,除了会命令行对应的那些字符串全部设置完毕以后,还会再多开一个空间存储NULL

所以其实,我们想要遍历所有的命令行参数的话,我们可以不用像前面那么麻烦,而是下面这样做

image-20231111172434494

image-20231111172519664

8.main函数的第三个命令行参数

其实main函数除了上面的两个参数以外,还有第三个参数

int main(int argc, char* argv[], char* env[])
{}

我们可以打印一下这个表

image-20231111173106911

image-20231111173133616

我们发现这个就是我们前面的env命令所打印出来的

image-20231111223815376

所以说,我们获取一个环境变量的时候,我们不用大费周章的使用getenv了。而且它还只能用一个

所以我们的C/C++代码一共是有两张向量表的

一张是命令行参数表,一张是环境变量表

所以说,我们的程序再运行的时候不是简单的只将程序加载到内存中,而且启动的时候有人要调用main函数,然后还要将这两张表给传过去

我们所运行的进程,都是子进程,bash本身在启动的时候,会从操作系统的配置文件中读取环境变量的信息,子进程会继承父进程交给我的环境变量!

所以往后的所有子进程,都会认识在bash中所定义的环境变量

所以说环境变量具有全局属性

  • 我们知道环境变量也是数据,进程具有独立性,当我们子进程对环境变量做出修改的时候,是不能影响父进程的,因为会写时拷贝
  • 环境变量被继承通常有两种方式:一种是直接继承,一种是main函数传参

除了上面的使用第三个命令行参数的方式获取环境变量,还可以使用这个第三方的变量environ来获取

extern char** environ

image-20231111224406466

image-20231111224538127

image-20231111224656416

9.如何验证环境变量是可以被继承的

当我们直接定义一个变量的时候,这样的话它并不是环境变量,因为在env中无法找到,而是一个本地变量。

直接在bash命令行中定义的变量就是本地变量,它就是一个shell层面、系统层面的概念

image-20231111175554063

如果我们想要将这个变量变为环境变量,我们可以这样做

export MY_VALUE=123

image-20231111175953537

这样的话就把这个变量导出了,导出到了bash的上下文中

然后在我们的程序中就可以发现了这个环境变量了

image-20231111180220378

这就说明mycmd这个程序拿到了bash的环境变量

即证明了环境变量被继承了

未来它的孙子,重孙子都是可以继承到这个环境变量的

如果我们要取消这个环境变量我们可以这样做

unset MY_VALUE

image-20231111180548848

我们前面的程序也随之找不到环境变量了

image-20231111180617670

10.本地变量与内建命令

我们已经知道,像这样的就是本地变量

image-20231111182132372

那么如何去查呢?我们可以用set,set可以查到系统当中所有的变量,包括本地变量,环境变量

set

image-20231111182312803

这些本地变量是不会被继承的,只会在本bash内部有效

那么什么时候需要用这些本地变量呢?我们可以看到这些PS1这些的变量

image-20231111212425478

这些其实就是我们命令行提示符的格式,如果是普通用户就是$和root就是#

image-20231111212724523

这个\的意思是如果这个命令没说完,可以下一行继续说

image-20231111212831145

image-20231111212851846

如果是上面这样的写法会提示>这样的形式,我们会发现这种形式正好就是PS2这个本地变量。

所以本地变量就是需要有一些符号不希望被继承下去的。

在set中其实把环境变量去掉,剩下的就都是本地变量了

就比如当我们写出如下代码的时候

image-20231111213741218

直接运行是这样的

image-20231111213803417

即便我们加上了本地变量,仍然是不行的

image-20231111213835679

唯有这样做,使用export将本地变量导为环境变量就可以了

image-20231111213921961

当我们不需要这个环境变量了,使用unset即可

image-20231111214001759

此时我们在set中,也找不到了

image-20231111214037130

可是我们会发现一个问题。

我们之前所说命令行中的指令都是bash的子进程,那么下面的现象我们看起来似乎没有问题

image-20231111214241699

但是我们之前说过这些

  • my是本地变量
  • 本地变量不会被继承
  • 指令都是bash的一个进程?

思考以上几点,感觉优点不对劲,既然echo会新起一个进程,而本地变量不会被继承,是如何打印的本地变量呢?

其实我们前面所说的指令都是bash的一个进程这句话不完全对,甚至是错的

其实指令应该分为两批

  1. 常规命令:通过创建子进程完成的
  2. 内建命令:bash不创建子进程,而是由自己亲自执行,类似于bash调用了自己写的或者系统提供的函数

也就是说如果是常规命令的话会有fork,如果是内建命令就不会fork

与之类似的指令还有cd -指令

因为如果cd创建了子进程,那么它改变的是子进程的路径,父进程的路径不应该受到影响,可是我们父进程的路径被修改了。

这就是因为cd也是一个典型的内建命令

在linux中有一个函数chdir就可以改变当前进程的路径

image-20231111215731393

所以我们可以模拟实现一个cd命令

image-20231111220136537

当我们运行的时候,发现还是不可以的

image-20231111220232456

这是因为我们这个./mycmd本身就会另起一个进程,在它的进程里面会改变路径,但是在我们当前的进程里面是不会改变的

那么我们可以将代码稍作修改,然后再这个代码里面的进程先观察一下

image-20231111220535146

我们可以看到当前进程的路径在改变之前是如下的

image-20231111220942141

改变之后就变为了/

image-20231111221006133

如果我们现在这个程序不是我们自己写的,而是bash本身。那么这个就是一个内建命令,就可以实现更换目录了

也就是说类似于这样的实现,假设我们当前的就是bash.c文件。直接在这里面进行特判即可,就可以不用创建子进程了,就可以看到目录变化了

image-20231111223429724

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java实现选择排序

图解 以下是Java实现选择排序的示例代码&#xff1a; public class SelectionSort {public static void selectionSort(int[] arr) {int n arr.length;// 遍历未排序部分的数组for (int i 0; i < n - 1; i) {// 在未排序部分中查找最小元素的下标int minIndex i;for (in…

MySQL 人脸向量,欧几里得距离相似查询

前言 如标题&#xff0c;就是通过提取的人脸特征向量&#xff0c;写一个欧几里得 SQL 语句&#xff0c;查询数据库里相似度排前 TOP_K 个的数据记录。做法虽然另类&#xff0c;业务层市面上有现成的面部检索 API&#xff0c;技术层现在有向量数据库。 用 MySQL 关系型存储 128 …

新学期帮娃把拖延症戒了!这个时间管理器太太太有用啦!

十个孩子九个拖延~ 不要唠叨&#xff0c;不要指责 时间流逝一眼可见&#xff0c;打败拖延症&#xff01; 赶紧把这款时间管理器用上 当当狸时间管理器 说起孩子没有时间观念、拖延症 每个老母亲都有一肚子苦水要倒&#xff5e;&#xff5e; 市面上有很多计时器&#xff0…

【k8s集群搭建(一):基于虚拟机的linux的k8s集群搭建_超详细_解决并记录全过程步骤以及自己的踩坑记录】

虚拟机准备3台Linux系统 k8s集群安装 每一台机器需要安装以下内容&#xff1a; docker:容器运行环境 kubelet:控制机器中所有资源 bubelctl:命令行 kubeladm:初始化集群的工具 Docker安装 安装一些必要的包&#xff0c;yum-util 提供yum-config-manager功能&#xff0c;另两…

主题讲座:全球增材制造现状与未来(暨香港科技大学广州|智能制造学域2024博士学位全额奖学金项目)

时间&#xff1a;2023 年11月16日&#xff08;星期四&#xff09;14:30 地点&#xff1a;合肥工业大学 学术会议中心三楼报告厅 主讲嘉宾&#xff1a;陈模军 助理教授 https://facultyprofiles.hkust-gz.edu.cn/faculty-personal-page/CHEN-Mojun/mjchen 报名表直达&#xff1…

Java 入门基础题

目录 1.输出一个整数的每一位 2.判定素数 3.求最大值方法的重载 4.输出闰年 5.打印 X 图形 6.数字9 出现的次数 7.计算分数的值 8. 模拟登陆 9.使用函数求最大值 10.斐波那契数列 星光不负赶路人&#xff0c;加油铁子们&#xff01;&#xff01;&#xff01; 1…

No205.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

人工智能与充电技术:携手共创智能充电新时代

人工智能与充电技术&#xff1a;携手共创智能充电新时代 摘要&#xff1a;本文探讨了人工智能与充电技术的结合及其在未来充电设施领域的应用。通过分析智能充电系统的技术原理、优势以及挑战&#xff0c;本文展望了由人工智能驱动的充电技术为未来电动交通带来的巨大变革与机…

java实现插入排序

图解 以下是Java实现插入排序的代码&#xff1a; public class InsertionSort {public static void main(String[] args) {int[] arr {5, 2, 4, 6, 1, 3};insertionSort(arr);System.out.println(Arrays.toString(arr)); // output: [1, 2, 3, 4, 5, 6]}public static void i…

【Linux】-文件系统的详解以及软硬链接

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

【Qt之QWizard】使用1

QWizard使用 描述方法枚举&#xff1a;enum QWizard::WizardButton枚举&#xff1a;enum QWizard::WizardOption枚举&#xff1a;enum QWizard::WizardStyle枚举&#xff1a;enum QWizard::WizardPixmap常用成员方法槽函数信号 示例设置标题添加page页设置按钮文本设置自定义按…

H5游戏源码分享-超级染色体小游戏

H5游戏源码分享-超级染色体小游戏 游戏玩法 不断地扩大发展同颜色的色块 用最少的步数完成游戏 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width,user-scalableno,init…

Linux shell编程学习笔记25:tty

1 tty的由来 在 1830 年代和 1840 年代&#xff0c;开发了称为电传打字机&#xff08;teletypewriters&#xff09;的机器&#xff0c;这些机器可以将发件人在键盘上输入的消息“沿着线路”发送在接收端并打印在纸上。 电传打字机的名称由teletypewriters&#xff0c; 缩短为…

学习samba

文章目录 一、samba介绍二、samba的主要进程三、配置文件四、例子 一、samba介绍 1、SMB&#xff08;Server Message Block&#xff09;协议实现文件共享&#xff0c;也称为CIFS&#xff08;Common Internet File System&#xff09;。 2、是Windows和类Unix系统之间共享文件的…

Android拖放startDragAndDrop拖拽Glide灵活加载堆叠圆角图,Kotlin(6)

Android拖放startDragAndDrop拖拽Glide灵活加载堆叠圆角图&#xff0c;Kotlin&#xff08;6&#xff09; Android拖放startDragAndDrop拖拽Glide加载堆叠圆角图&#xff0c;Kotlin&#xff08;5&#xff09;-CSDN博客文章浏览阅读1.3k次。&#xfeff;&#xfeff;Android Dyna…

Python---集合中的交集 、并集 | 与差集 - 特性

用 & 来求两个集合的交集&#xff1a;-----键盘上的7上的符号&#xff0c;shift 7 同时按 用 | 来求两个集合的并集&#xff1a; -----键盘上的7上的符号&#xff0c;shift 同时按&#xff08;就是enter键上面那个|\ &#xff09; 用 - 来求两个集合的差集&#xff…

dbeaver导入sql脚本报错:unhandled event loop exception java heap space

在DBeaver里执行一个有8w条数据的sql文件&#xff0c;只保存了2k条 错误原因见&#xff1a; https://blog.csdn.net/liu_feng_zi_/article/details/122578880文章作者所描述的&#xff1a; 使用dbeaver连接MySQL数据库&#xff0c;在通过sql脚本插入数据&#xff0c;或将插入语…

模拟散列表(哈希表拉链法)

维护一个集合&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个整数 x&#xff1b;Q x&#xff0c;询问整数 x 是否在集合中出现过&#xff1b; 现在要进行 N 次操作&#xff0c;对于每个询问操作输出对应的结果。 输入格式 第一行包含整数 N&#xff0c;…

【论文阅读】(VAE-GAN)Autoencoding beyond pixels using a learned similarity metric

论文地址;[1512.09300] Autoencoding beyond pixels using a learned similarity metric (arxiv.org) / 一、Introduction 主要讲了深度学习中生成模型存在的问题&#xff0c;即常用的相似度度量方式&#xff08;使用元素误差度量&#xff09;对于学习良好的生成模型存在一定…

【C++】类与对象 I

类与对象 I &#xff1a; 前言&#xff1a;&#xff08;C&#xff09;面向过程 和&#xff08;C&#xff09;面向对象 初步认识前言&#xff1a;类的引入一、类的介绍二、类的定义&#xff08;一&#xff09;class 语法&#xff08;二&#xff09;类的两种定义方式&#xff1a;…