【Linux从入门到放弃】环境变量

news2024/12/26 23:01:55

🧑‍💻作者: @情话0.0
📝专栏:《Linux从入门到放弃》
👦个人简介:一名双非编程菜鸟,在这里分享自己的编程学习笔记,欢迎大家的指正与点赞,谢谢!

在这里插入图片描述

文章目录

  • 前言
  • 一、环境变量是什么?
    • 1.1 概念
    • 1.2 从Linux角度认识环境变量
    • 1.3 查看环境变量
    • 1.4 获取环境变量
      • 1.4.1 通过命令行第三个参数
      • 1.4.2 通过第三方变量environ
      • 1.4.3 通过函数获取
    • 1.5 环境变量概念再总结
    • 1.6 环境变量的数据从哪来?
  • 二、main函数的参数列表
    • 2.1 参数介绍
    • 2.2 命令行参数的含义
  • 三、进程优先级
    • 3.1 概念
    • 3.2 为什么有优先级呢?
    • 3.3 查看系统进程优先级 (`ps -l`)
    • 3.4 更改进程优先级
  • 总结


前言

  提到环境变量,大家应该都不会陌生,不管学习Java还是Phython都需要去安装环境变量,尤其是我自己在做深度学习时配置环境变量简直了,那叫一个惨,真的是莫名其妙不知道是哪里出的错,总之就是很难!那么今天的目的就是解释一下什么是环境变量。


一、环境变量是什么?

1.1 概念

  环境变量是在操作系统当中由系统在开机之后帮我们维护的一些系统运行时的动态参数。

1.2 从Linux角度认识环境变量

  环境变量因为所针对的场景不同,应用的软件不同而会有不同的种类。

  1. 我们在Linux中写的代码在编译之后形成的可执行程序为什么运行的时候要加上./呢?
  2. 可执行程序它是工具吗?是指令吗?比如我们可以执行指令file /user/bin/ls其实发现我们平时用的指令本质就是拿C写的可执行程序。当然我们自己写的可执行程序也可以通过这样的方式来查看。

那么这两种有什么区别呢? 答案是没有任何区别,只不过那些指令被纳入到了Linux基本指令的范畴中了。

  1. 我们可以从这样的一个角度出发,为什么系统的指令(可执行程序)不用加./,而运行我自己写的非得加上./呢?反过来说,我也想让我的程序不用加上./就可以运行该怎么做呢?

我们自己运行程序的方式其实是采用相对路径的方式来完成的,当然绝对路径的方式也是可以的。而之所以默认的指令可以不加./是因为在系统中存在一个环境变量,可以通过这个环境变量帮助我们在系统中特定路径下去搜索对应的命令。而这个环境变量是PATH,可以通过echo $PATH查看变量内容。

//我自己机器对应的环境变量
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/zhuxu/.local/bin:/home/zhuxu/bin

系统的指令在执行时会在这个环境变量中一个个查找,找到了就直接执行,而我们对应的可执行程序对应的路径肯定不在里面,因此在执行时就得加上路径。
在这里插入图片描述
通过上图可以看到ls命令在/user/bin目录下,而这个就在PATH环境变量中(包含多个路径,以冒号作为分隔符),但是自己的可执行程序并不在其中。那我们将这个路径添加到环境变量中应该就可以直接执行了吧。
在这里插入图片描述
可以通过上面这条指令给环境变量中添加那条路径,再查看环境变量明显发现多了一条路径,而这就是我们自己写的可执行程序对应的路径。这样就可以不用加./而直接运行程序了。

  1. 除了上面的做法,那我们还可以直接将可执行程序添加到环境变量中的系统默认路径下——而这种方式就相当于Linux下的软件安装。当然不要了的话可以直接删除——卸载。

1.3 查看环境变量

env //很简单,这个命令就可以查看所有的环境变量

在这里插入图片描述
常见环境变量:

PATH : 指定命令的搜索路径
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。

1.4 获取环境变量

  我们一般写main函数时都是不写参数的,但是人家其实是有参数的,而且还有三个参数,分别是:int argc、char *argv[]、char *envp[],前两个大家应该还挺熟悉,第三个参数被称为环境变量表。
  这个环境变量表是一个指针数组,每一个位置存放着地址数据,基本上指向一个个字符串,最后必须以NULL结尾。

1.4.1 通过命令行第三个参数

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

1.4.2 通过第三方变量environ

environ是一个二级指针,和命令行的第三个参数是一样的,都指向那张环境变量表。
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。

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

到这里我们就能明白在进程内部本身就有环境变量。然后呢?有什么用呢?我们是可以拿到一张环境变量表,难道我们要用某个环境变量的时候还得从这个表一个个去查找吗?那岂不是太挫了。

1.4.3 通过函数获取

//通过环境变量命来获取对应的环境变量
char *getenv(const char *name);
#include <stdio.h>
#include <stdlib.h>

int main()
{
	char *path=getenv("PATH");
	if(path==NULL) perror("getenv");
	else printf("PATH:%s\n",path);
	return 0;
}
  1. 当然可以写一个获取当前路径的方法,那最终出来的效果是和系统本身指令pwd是一样的。
  2. 如果你想写一个只允许你自己执行的进程,那么可以获取USER这个环境变量,只要它的用户和你设置的用户名不同那就不能够执行。

1.5 环境变量概念再总结

  1. 环境变量本质就是一张内存级的一张表,这张表由用户在登陆系统的时候,进行给特定用户形成属于自己的环境变量表。
  2. 环境变量中的每一个都有自己的用途:有的是进行身份认证的,有的是进行确认当前路径的,有的是进行路径查找的,而有的是进行动态查找的等等。
  3. 每一个环境变量都有自己特定的应用场景。
  4. 每一个元素都是K-V类型的,不同名字对应不同的内容。

1.6 环境变量的数据从哪来?

  它是一张内存级的表,那么内存中的数据在没有加载到内存之前是从哪来的呢?都是从系统的相关配置文件中读取进来的
  在家目录下,有这么两个文件: .bash_profile.bashrc,它们本质都是 shell 脚本,每次重新登陆的时候,系统都会重新读取配置文件,将配置文件中的脚本一执行从而形成对应的环境变量。
  我们在执行命令时都是bash去执行的,除了这个,它也支持命令行式的定义变量export myval=100,这就相当于在bash内部定义了myval和100的字符串。
  每当我们登陆了系统之后,操作系统就会创建shell进程,它的功能是读取命令和命令行的。当我们在命令行中设置了刚才那个变量为100,那么shell就会将该命令以字符串的形式读入其中,并且在shell内部会维护一张环境变量表,然后通过一个指针指向那个字符串,也就相当于把这个命令导进了环境变量中使之成为环境变量中的一员。要知道,所有的命令都是shell的子进程,所以当执行命令的时候shell就会将自己的表传给它的子进程。

这也间接说明了环境变量具有全局属性,它是可以被相关子进程继承下去的。

  那怎么证明呢?

  1. 先将该命令导入环境变量中:export hello="world"
  2. 查看环境变量是否导入成功。
    在这里插入图片描述
  3. 编写代码通过函数调用的方式看是否能获取到刚设置的环境变量。
int main()
{
  char *path=getenv("hello");
  if(path==NULL)
    perror("getenv");
  else printf("%s\n",path);
  return 0;
}

注:
命令行式的导入环境变量不加export的话同样也是可以通过命令行的方法将设置的对应变量打印出来,但是函数调用的方法是不行的,为什么呢?原因就是这种方法定义出来的变量属于本地变量,只在shell内部有效,不能被子进程继承。

二、main函数的参数列表

2.1 参数介绍

int main(int argc,char *argv[])
argv:一张表,指针数组,
argc:指针数组元素的个数。
int main(int argc,char *argv[])
{
	int i=0;
	for(;i<argc;++i)
	{
		printf("argv[%d]->%s\n",i,argv[i]);
	}
	return 0;
}

在这里插入图片描述

  1. 当我们在命令行中这样输入,在shell看来他就是一个字符串,那就以空格为分隔符拆成一个个子串,./myproc为可执行程序,后面的一个个子串为参数选项。而那张参数表分别指向这一个个子串,最后NULL结尾。
  2. 那谁制作的这张表呢?当然是bash,也就是在执行命令的时候就将这张表做好了,而我们写的这个进程(子进程)使用这张表。
  3. bash(父进程)创建出来了一个个参数,然后子进程使用。

2.2 命令行参数的含义

可以根据命令行的参数选项不同而表现出不同的功能。

看下面的代码:

void Usage(const char* name)
{
  	printf("\nUsage: %s -[a|b|c]\n\n",name);
  	exit(0);
}

int main(int argc,char *argv[])
{
  	if(argc!=2) Usage(argv[0]);
  
  	if(strcmp(argv[1],"-a")==0) printf("打印当前目录下的文件名\n");
  	else if(strcmp(argv[1],"-b")==0) printf("打印当前目录下的文件的详细信息\n");
  	else if(strcmp(argv[1],"-c")==0) printf("打印当前目录下的文件名(包含详细信息)\n");
  	else printf("其他功能,待开发\n");
}

代码功能:实现了一个必须按照正确命令行参数规范输入而执行打印效果的demo。
当命令行参数个数为两个时才进行打印,若不是,就会进入Usage函数,这个函数功能就是告诉你应该怎样去正确的输入命令行。

在这里插入图片描述

从上图可以看出,当没有按照规范输入就会给出应该输入的规范模板,当正确输入时就会根据参数选项的不同而表现出不同的功能。这也就和ls命令和不同的选项而表现出不同的功能输出。

三、进程优先级

3.1 概念

  优先级指的是CPU资源分配的先后顺序
  当然优先级高的进程首先获取到CPU资源并执行,就可以把那些不重要的进程安排在其他位置,让优先级高的进程先运行,这样可以大大改善系统的整体性能。

3.2 为什么有优先级呢?

  举个简单例子,在学校里,每到中午的时候我们都要去食堂买饭,往往伴随着排队买饭的现象,原因就是卖饭窗口少,学生人数多。而优先级的出现就在于CPU资源有限。
  正是因为CPU资源的有限,导致了众多进程需要竞争获取资源,必定会有先后顺序,进而会有优先级的出现让进程使用CPU资源有一定的先后顺序。

3.3 查看系统进程优先级 (ps -l)

在这里插入图片描述

PRI :代表这个进程可被执行的优先级,其值越小越早被执行
NI :该进程的nice值,修正数据

  每个进程都有自己的PRI,而这个数字则代表着自己的执行优先级,也就是该程序被CPU执行的先后顺序,此值越小进程的优先级别越高,NI表示修正数据,这个东西是Linux操作系统独有的,在其它操作系统中是没有的。
  当然,一个进程最终的优先级不只是仅仅看PRI的大小,还有需要看Ni的值。PRI(new)=PRI(old)+NI
  NI值为负值的时候,那么该程序将会优先级数值将变小,即其优先级会变高,则其越快被执行。所以,在Linux下调整进程优先级就是调整进程NI值,NI其取值范围是-20至19,一共40个级别。

3.4 更改进程优先级

用top命令更改已存在进程的nice:top

进入top后按“r”–>输入进程PID–>输入nice值

当然除了这种还有其它方式,具体是那种在这里不多介绍,毕竟这个点不是很重要。有兴趣可以自己了解一下。


总结

此篇博客主要是对操作系统中的环境变量以及参数列表,进程优先级做了陈述,重点还是放在环境变量的理解上。

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

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

相关文章

mongodb使用简单文档

1、mongodb安装与卸载 1.1、安装 python -m pip install pymongo 或 pip install pymongo如果要安装指定版本&#xff1a; python -m pip install pymongo3.5.1对已有的版本进行升级&#xff1a; python -m pip install --upgrade pymongo1.2、卸载 pip uninstall pymongo…

【MATLAB】史上最全的5种数据插值算法全家桶

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有5种数据插值算法&#xff0c;绝对不亏&#xff0c;知识付费是现今时代的趋势&#xff0c;而且都是我精心制作的教程&#xff0c;有问题可随时反馈~也可单独获取某一算法的代码&#xff08…

使用vant list实现订单列表,支持下拉加载更多

在公司项目开发时&#xff0c;有一个需求是实现可以分页的订单列表&#xff0c;由于是移动端项目&#xff0c;所以最好的解决方法是做下拉加载更多。 1.在页面中使用vant组件 <van-listv-model"loading":finished"finished"finished-text"没有更…

kubernetes|云原生| 如何优雅的重启和更新pod---pod生命周期管理实务

前言&#xff1a; kubernetes的管理维护的复杂性体现在了方方面面&#xff0c;例如&#xff0c;&#xff50;&#xff4f;&#xff44;的管理&#xff0c;服务的管理&#xff0c;用户的管理&#xff08;&#xff32;&#xff22;&#xff21;&#xff23;&#xff09;&#xf…

RT-DETR算法优化改进:SCConv,空间和通道重建卷积 | CVPR2023 | 卷积变体大作战

💡💡💡本文改进:SCConv(空间和通道重建卷积),一个即插即用的架构单元,可以直接用来替代各种卷积神经网络中的标准卷积。 1)放入Neck RepC3后面; RT-DETR魔术师专栏介绍: https://blog.csdn.net/m0_63774211/category_12497375.html ✨✨✨魔改创新RT-DETR �…

98.qt qml-使用曲线图综合示例、支持多种鼠标交互、支持百万数据显示(已适配黑白风格)

在上章我们只是简单实现了曲线图和折线图的显示: 79.qt qml-如何在QML中使用QCustomPlot之曲线/折线示例(已适配黑白风格)_qml 折线图_诺谦的博客-CSDN博客 所以本章实现综合示例、并添加多种功能如下所示: 详细显示:鼠标任意移动显示具体值内容鼠标右击: 弹出菜单栏,支持…

华夏ERP打包手册

Maven安装及环境配置 1.下载 浏览器搜索maven点击apache Maven 2.选择安装目录&#xff0c;注意不能有中文 3.环境变量配置 点击计算机右键属性>高级系统设置>环境变量 新建系统变量 MAVEN_HOME 变量值是安装目录 进入path点击新建点击编辑&#xff0c;写入% MAVEN_H…

【Unity】单例模式及游戏声音管理类应用

【Unity】单例模式及游戏声音管理类应用 描述 在日常游戏项目开发中&#xff0c;单例模式是一种常用的设计模式&#xff0c;它允许在应用程序的生命周期中只创建一个对象实例&#xff0c;并提供对该实例的全局访问点。通过使用单例模式&#xff0c;可以提高代码的可维护性和可…

人工智能轨道交通行业周刊-第65期(2023.10.30-11.19)

本期关键词&#xff1a;高铁自主创新、智慧城轨、调车司机、大模型垂直应用、大模型幻觉 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通RailMetro轨道…

PaddlePaddle:开源深度学习平台

深度学习作为人工智能领域的重要分支&#xff0c;正在全球范围内得到广泛应用。而在构建和训练深度学习模型时&#xff0c;选择一个高效、易用且功能强大的开源平台是至关重要的。PaddlePaddle&#xff08;即飞桨&#xff09;作为国内领先的深度学习平台&#xff0c;一直以来都…

【代码随想录】算法训练计划23

1、669. 修剪二叉搜索树 题目&#xff1a; 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&…

在 C# 程序中注入恶意 DLL

为什么 Windbg 附加到 C# 程序后&#xff0c;程序就处于中断状态了&#xff1f;它到底是如何实现的&#xff1f;其实简而言之就是线程的远程注入&#xff0c;这一篇就展开说一下。 实现原理 1. 基本思路 WinDbg 在附加进程的时候&#xff0c;会注入一个线程到 C# 进程 中&…

设计模式-行为型模式-责任链模式

一、什么是责任链模式 责任链模式是一种设计模式。在责任链模式里&#xff0c;很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递&#xff0c;直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求&…

RobotFramework之如何使用数据驱动(十二)

学习目录 引言 数据驱动是什么&#xff1f; 非驱动方式测试案例 通过添加Template模板的方式&#xff0c;实现数据驱动 将参数放在变量文件中&#xff0c;实现数据驱动 引言 大家平时在写接口或者UI自动化用例的时候&#xff0c;是否遇到这种情况&#xff1a; 写了很多条…

手搓哈希表、列表、队列,只为了用C语言快速求解华容道游戏,我不是大佬,只是一个游戏算法爱好者

背景 多年前曾经写过C语言求解华容道&#xff0c;当时没有用到哈希表&#xff0c;导致整个查重搜索数组过大&#xff0c;每次求解都得花上数分钟的时间&#xff0c;如今时过境迁&#xff0c;对数据结构和算法有了更深的理解&#xff0c;所以得把这一块补上了。(其实就是最近想…

UE5制作场景时的小技巧和注意事项

UE5制作场景时的小技巧和注意事项 一、场景相关 1.1灯光 1.1.1构建完光照,发现场景都是黑的 可能是所有灯光是静态灯光,把skylight改为动态,如果改完之后还是黑色的,那就在构建一次,就应该没问题了 1.1.2场景中有多个动态光会造成阴影闪烁 需要将skylight变为固定 1…

CI/CD - jenkins

目录 一、部署 1、简介 2、部署 二、配置 三、实时触发 四、自动化构建docker镜像 五、通过ssh插件交付任务 六、添加jenkins节点 七、RBAC 八、pipeline 九、jenkins结合ansible参数化构建 1、安装ansible 2、新建gitlab项目 3、jenkins新建项目playbook 一、部…

linux进程之进程的优先级➕环境变量

文章目录 1.优先级的认识1.1优先级的介绍1.2初识优先级1.3ps指令1.4查看/修改进程的优先级1.5对优先级的认识1.6对进程的深一步理解 2.环境变量2.0环境变量相关的命令2.1环境变量的概念2.2常见/查看环境变量2.3环境变量的作用2.4修改环境变量1.将zombie可执行程序放到PATH现有的…

IOS object-c大屏图表 PNChart 折线图 曲线图

折线图是排列在工作表的列或行中的数据可以绘制到折线图中。折线图可以显示随时间&#xff08;根据常用比例设置&#xff09;而变化的连续数据&#xff0c;因此非常适用于显示在相等时间间隔下数据的趋势。在折线图中&#xff0c;类别数据沿水平轴均匀分布&#xff0c;所有值数…

​软考-高级-系统架构设计师教程(清华第2版)【第19章 大数据架构设计理论与实践 (P691~716)-思维导图】​

软考-高级-系统架构设计师教程&#xff08;清华第2版&#xff09;【第19章 大数据架构设计理论与实践 &#xff08;P691~716&#xff09;-思维导图】 课本里章节里所有蓝色字体的思维导图