【Linux】环境变量

img

Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。


在这里插入图片描述

0. CPU是如何执行进程的?

CPU执行进程时分为两种模式:1. 并发 2. 并行.

并行是当有多个CPU时,每个进程都可以物理意义上的同时运行

并发是指每一个进程在一定的时间内轮流的使用CPU,是逻辑上的同时运行

一定的时间我们称之为时间片.每个进程在时间片结束后,需要离开CPU.这一过程我们称为进程切换(进程切换基于时间片轮转的调度算法)

所以我们在C++里写一个死循环并不会让整个电脑瘫痪.

那么刚刚CPU下次怎么知道自己上次执行到了哪里?难道每一次都要从头开始执行嘛?

在CPU中有许多寄存器,他们帮助CPU提高效率.

我们先来简单的理解下寄存器是什么?

我们之前介绍过函数栈帧.那么一个函数结束之后,他的局部变量不是被销毁了嘛?为什么可以传到函数外面去.

在销毁之前,将其存到了CPU的寄存器当中.所以外部程序可以通过寄存器来接收到已经销毁的局部变量的值.

所以寄存器的作用为:将进程中的高频数据存入寄存器中,以提高CPU的工作效率

CPU中有一个叫做eip的寄存器,永远指向运行指令的下一条.所以CPU执行当前语句之后会知道自己接下来要执行什么语句.

那么回答最开始的问题.CPU如何知道当下要运行的这个进程上一次执行到哪里了?

进程的TASK_STRUCT中有一个专门维护CPU信息的结构体,要从CPU中下来的时候,会用这个结构体去保存CPU中关于运行的相关信息(例如EIP当前指向的位置就会被保存下来).

1. 环境变量是什么?

这个词如果在WINDOWS中配置过Python等语言一定听说过,其中最折磨的部分就是修改系统环境变量

image-20231108194114495

在Linux中同样有这么一个概念.我们先来看看接下来这个现象

#include <stdio.h>
int main()
{
    printf("hello environment!\n");
    return 0;
}

这是一段简单的程序.我们一样先编译再运行

gcc -o proce proce.cpp && ./proce

在屏幕上打印出了"hello environment!"

image-20231108194603247

那我们如果返回到上一个目录中,输入./mycode还能运行吗?显然是不能的,我们需要输入完整的路径.例如我这里是**./8.4/mycode**

才可以运行

image-20231108194715413

那为什么我们输入系统中的ls指令或其他指令时不需要这样输入路径然后运行呢?

因为系统中会自己去已经存在的路径中寻找.这个路径存在环境变量中.(可以理解为这个系统环境中的全局变量)

echo $PATH

我们可以在屏幕上打印出当前的环境变量

image-20231108194918095

我们可以把自己上面写的程序路径加入到PATH当中就可以直接输入了

PATH=$PATH:你的程序绝对路径

2. 使用环境变量

我们在命令行中输入env,就可以查看当前所有的环境变量

image-20231108195323929

可以看到很多有意思的变量.

BASH: 当前使用的命令行解释器的路径

PWD:当前工作路径

HOME:家目录.(每次我们登录服务器时,系统会先判断你为什么用户,然后执行cd 环境变量中对应的目录,就是我们开机的样子)

我们可以看出,其为一个key-value的结构.

在代码中我们可以使用getenv来获取想要的环境变量值.

man getenv

image-20231108195918708

其在3号手册中,为库函数.返回值为获取的变量值.

我们简单来试一下

#include <stdlib.h>
int main()
{
    printf("PATH:%s",getenv("PATH"));
    return 0;
}

image-20231108200450692

这就是使用它的方法.

3. 命令行参数表与环境变量表

我们通常写的main函数是长这个样子的

int main()

他是没有参数的

我们也可以将他写成这个样子

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

这是两张核心向量表!

argc:传入的argv参数数量

argv:命令行参数,其中第一个为当前可执行程序的名称,之后为传入的参数.以NULL结尾

env:当前进程中的环境变量.以NULL结尾

我们可以写一个这样的程序来获取我们输入的命令行参数

#include <stdio.h>
int main(int argc,char* argv[])
{
	for(int i=0;i<argc;i++)
    	{
        	printf("%s\n",argv[i]);
    	}
	return 0;
}

image-20231108201332196

因为main函数也是被启动的函数,启动其的函数会向其传递该参数表.以此来为指令,工具,软件等提供命令行选项的支持.

我们也可以通过同样的方式来获取环境变量

#include <stdio.h>
int main(int argc,char* argv[],char* env[])
{
	for(int i=0;env[i];i++)
    	{
        	printf("%s\n",env[i]);
    	}
	return 0;
}

我们还可以通过extern char **environ来获取

#include <stdio.h>
int main(int argc,char* argv[],char* env[])
{
	extern char **environ;
    int i = 0;
    for(; environ[i]; i++)
    {
        printf("%d: %s\n", i, environ[i]);
    }
    return 0;
}

4. 本地变量 内建命令 常规命令

本地变量只能在本bash中,并不会被创建的子进程所继承.类似于局部变量,而环境变量相当于全局变量

之前我们提到过BASH只负责解释命令,而执行命令是通过创建子进程来完成的.这部分我们称为常规命令

而有一部分命令是BASH自己去执行的

例如cd(若创建子进程去切换目录,最终切换的是子进程的工作空间,并不会改变当前进程)

我们可以使用如下的方式验证下echo是内建命令还是常规命令

var=1000
echo $var

前面我们提到过,var为本地变量,只能在当前进程使用.若echo出来了var的值,则说明BASH没有创建子进程去执行echo这条指令

而有一部分命令是BASH自己去执行的

例如cd(若创建子进程去切换目录,最终切换的是子进程的工作空间,并不会改变当前进程)

我们可以使用如下的方式验证下echo是内建命令还是常规命令

var=1000
echo $var

前面我们提到过,var为本地变量,只能在当前进程使用.若echo出来了var的值,则说明BASH没有创建子进程去执行echo这条指令

image-20231108203040067
image-20230905164632777

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ppeua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值