✨个人主页: Yohifo
🎉所属专栏: Linux学习之旅
🎊每篇一句: 图片来源
🎃操作环境: CentOS 7.6 阿里云远程服务器
- Perseverance is not a long race; it is many short races one after another.
- 毅力不是一场漫长的比赛;是许多短跑一个接一个。
文章目录
- 📘前言
- 📘正文
- 📖环境变量
- 🖋️环境变量列表
- 🖋️添加环境变量
- 🖋️获取环境变量
- 📖主函数参数
- 🖋️三个参数
- 🖋️选项调用
- 📖进程优先级
- 🖋️优先级查看
- 🖋️优先级修改
- 📖进程特点
- 📘总结
📘前言
环境变量
是一个即陌生又熟悉的词,说陌生是因为大多数普通用户都接触不到 环境变量
配置,说熟悉是因为很多程序又都离不开 环境变量
,比如编写 Java
时需要提前安装 jdk
,配置好 Java
的环境,才能正常编写代码,python
也是需要配置编码环境;而在我们的 Linux
中也有环境变量
,由 环境变量
构成的集合称做 环境变量表
;我们还可以调整 进程
的优先级,使得 进程
运行更加灵活
📘正文
📖环境变量
首先需要先来看看什么是 环境变量
- 一般是指在操作系统中用来指定操作系统运行环境的一些参数
- 例如在编译程序时,我们是不关心动态库位于什么地方,编译器链接时也只需要通过对应的
环境变量
就能找到动态库进行链接 环境变量
有着自己的特殊用途,还有有些具有全局属性,可以供所有进程
共享
环境变量
有很多个,把它们聚在一起管理,就构成了 环境变量列表
环境变量列表
中的常见 环境变量
:
PATH
系统命令搜索路径USER
当前用户名PWD
当前所处路径
我们可用通过指令 echo $NAME
查看当前环境变量信息(NAME
指环境变量名)
//比如查看用户信息$ echo $USER
🖋️环境变量列表
下面来看看 环境变量列表
长什么样
通过指令查看
$ env
环境变量表是以指针数组的形式存储的
也可以通过 set
指令查看 环境变量表
,不过 set
指令显示的内容比 env
多得多,因为 set
还会显示 本地环境变量
信息
$ set //显示更加丰富的环境变量表
这里简单说一下 PATH
的作用
Linux
中的各种指令都是用C语言
编写的程序,所以:运行指令 == 运行程序PATH
环境变量中有存储各种指令(程序)的路径,当我们直接输入指令时,OS会根据PATH
提供的路径搜索程序,找到了就会直接运行对应指令(程序)- 而我们自己编写的程序则是需要通过
./可执行程序
的方式运行,因为此时路径不被包含在PATH
变量中 - 总之:PATH 存储路径中若包含程序,可以直接通过程序名运行程序
- 这就是各种指令,如
ls
、pwd
、touch
的运行原理
我们可以通过这一特性,将自己的可执行程序路径添加到 PATH
变量中
//注意:路径为绝对路径//不能写成 export PATH=路径 这样会把所有指令都覆盖$ export PATH=$PATH:/home/Yohifo/linux/Explore/code/Test_2_21
现在可以像指令一样直接运行程序
注意: 普通用户添加的环境变量只有本次登录有效,下次再登录时,环境变量列表会被重置
普通用户修改 环境变量列表
没什么大问题,但 root
需要谨慎了,避免造成严重后果
除此之外,我们还可以把程序写在 /usr/bin
目录下,此时也是可以直接通过程序名运行程序的
如上就是安装、卸载应用原理
🖋️添加环境变量
shell
可以读取到命令和命令行,我们可以直接通过命令的方式添加 环境变量
先来看看比较简单的 本地变量
添加
环境变量表
具有全局属性,可以供所有子进程共享,倘若我们不想让 环境变量
被共享,可以设置 本地变量
$ TEST=private //可以直接在命令行中添加本地变量
现在的 TEST
环境变量是不被子进程共享的
如果想删除已经设置的 本地环境变量
,可以通过 unset NAME
移除设置
$ unset TEST //移除已设置的本地环境变量
想让 TEST
进入 环境变量表
也很简单,只需要加上关键字 export
$ export TEST=public //此时环境变量已进入环境变量表
🖋️获取环境变量
环境变量
针对的是特定的人在特定场合干特定的事,这句话读起来有点绕,实际上:
- 有许多
环境变量
存储的是用户的个人信息,不同用户的环境变量表
各不相同 - 我们可以利用
环境变量
做信息验证,根据不同变量(选项)执行不同操作
比如
ls
指令是显示当前目录下的文件信息,而ls -a
则是显示详细信息,原理很简单,调用ls
程序时传递了-a
这个选项,使得程序一对比,就知道要执行显示详细信息这个操作
环境变量表具有全局属性,程序运行时,环境变量表会传递给程序使用
因此我们可以在程序中获取 环境变量
- 通过全局变量
environ
(char**
类型)获取 - 通过函数
getenv(NAME)
获取,这个比较常用 - 通过
main
函数中的第三个参数char* envp[]
获取
前两种方式比较简单,可以通过一个小程序观察到,而最后一种方式 需要结合主函数参数 的知识观察,将放在下一个部分详细讲解
先来看看前两种方式获取 环境变量
#include<iostream>#include<stdlib.h> //getenv 需要使用这个头文件using namespace std;extern char** environ; //声明使用int main(){ //cout << "Hello environment variable!" << endl; //你好环境变量! int pos = 0; while(pos < 5) { cout << environ[pos] << endl; //获取部分环境变量信息 pos++; } cout << endl << "========================" << endl << endl; //通过函数获取 cout << "PWD=" << getenv("PWD") << endl; return 0;}
可以自己尝试通过
getenv
函数验证本地变量不进入环境变量表这个现象
指令 pwd
实现非常简单,通过 getenv("PWD")
获取信息,再输出即可,我们可以自己实现 mypwd
#include<iostream>#include<stdlib.h>using namespace std;int main(){ //调用程序,获取环境变量信息 cout << getenv("PWD") << endl; return 0;}
一些不带选项,且比较简单的指令,我们是 可以直接利用函数获取 环境变量
模拟实现
📖主函数参数
main
函数有两种写法:带参与不带参,平常我们都是使用不带参数的 main
函数作为程序入口,对于函数参数很少关注,今天就来看看 main
函数中的参数吧
🖋️三个参数
main
函数中有三个参数,分别是:
int argc
传入程序中的元素数,./程序名
算一个char* argv[]
传入程序中的元素表,由bash
制作,传给main
函数char* envp[]
环境变量表,所谓全局性就是指main
函数可以通过此参数获取到环境变量表的信息
如何证明它们存在呢?
程序就是最好的证明
#include<iostream>using namespace std;int main(int argc, char* argv[], char* envp[]){ cout << "现在传入的有效元素数为:" << argc << endl; cout << "==========================" << endl; cout << "通过元素表打元素信息" << endl; int pos = 0; while(pos < argc) { cout << argv[pos] << endl; pos++; } cout << "==========================" << endl; cout << "使用环境变量表获取前五个环境变量信息" << endl; pos = 0; while(pos < 5) { cout << envp[pos] << endl; pos++; } return 0;}
main 函数中的三个参数各有各的作用
enpv
也可以获取环境变量,效果等价于 environ
环境变量表
能被共享的本质: 环境变量表会通过传参数的形式传给程序使用
🖋️选项调用
argv
可以实现指定指令完成指定功能的任务
首先我们需要在程序中提前设置好不同选项的运行结果
#include<iostream>#include<string.h>#include<stdlib.h>using namespace std;//打印提示信息void Usage(const char* str){ cout << str << " -[a | b | c]" << endl;}int main(int argc, char* argv[], char* envp[]){ //首先进行身份检验 if(strcmp(getenv("USER"), "Yohifo") != 0) { cout << "当前用户为:" << getenv("USER") << endl; cout << "非法使用他人程序,操作被拒绝!" << endl; return 0; } //确保选项只有一个 if(argc != 2) { cout << "指令错误,尝试重新输入" << endl; Usage(argv[0]); return 0; } //验证成功后,进行选项分流 if(strcmp(argv[1], "-a") == 0) { cout << "执行 a 任务" << endl; cout << "…………………………" << endl; cout << "任务执行完成" << endl; } else if(strcmp(argv[1], "-b") == 0) { cout << "执行 b 任务" << endl; cout << "…………………………" << endl; cout << "任务执行完成" << endl; } else if(strcmp(argv[1], "-c") == 0) { cout << "执行 c 任务" << endl; cout << "…………………………" << endl; cout << "任务执行完成" << endl; } else { cout << "指令错误,尝试重新输入" << endl; Usage(argv[1]); return 0; } return 0;}
通过不同的选项,调用不同的功能,这就是 main
函数参数存在的意义
选项会同程序名一起,构成一张表,传给 char* argv[]
参数
这种玩法叫做 命令行参数
,后续学习中将会经常用到
📖进程优先级
进程
还有优先级之分,优先级高的 进程
会被优先调用
CPU 资源是有限的,需要合理分配
Linux
给我们提供了修改进程
优先级的权限,目的就是让我们对多任务运行进行合理处理,提高系统运行效率
🖋️优先级查看
在 进程
的PCB
信息中,还包含了这些信息:
UID
身份标识PRI
进程优先级,默认为 80NI
进程修正值,这个只有Linux
中有,配合修改优先级,范围为[-20, 19]
我们可以通过 ps
指令查看进程优先级情况
//注:其中的 myfile 是可执行程序名$ ps -al | head -1 && ps -al | grep myfile //查看进程优先级信息
🖋️优先级修改
进程优先级
可以被修改,但很少有人会主动修改
修改步骤
- 输入
top
指令进入任务管理器 - 输入
r
进入修改模式 - 再根据想要修改的进程,输入
PID
- 最后输入
NI
值,完成修改
注意:
NI
值区间为[-20, 19]
,设置时超出部分无效- 修改优先级时,
最终优先级
=初始优先级
+NI值
,优先级的修改行为并不是连续的,每次都是在最开始的基础上进行修改(默认为 80) - 调度器不允许存在
优先级失衡
的情况,因此优先级修改不能太激进
📖进程特点
下面来简单小结一下进程的特点
- 竞争性:CPU 资源有限,
进程
间存在竞争 - 独立性:
进程
是相互独立运行的,互不干扰 (重要) - 并行:多个
进程
可以在多个 CPU 上同时运行 - 并发:在一个 CPU 下采用
进程
切换的方式运行多个进程
📘总结
以上就是有关进程学习【环境变量】的全部内容了,本文主要研究对象是 环境变量
,知道了 环境变量表
的存在,以及主函数是如何得到 环境变量表
表并实际运用的;最后还谈到了 进程优先级
问题,学习了优先级修改的相关指令;进程
最大的特性之一就是 独立性
,父子进程
间会发生 写时拷贝
机制,这种神奇的现象是如何产生的呢?敬请期待下篇中关于 进程地址空间
的相关文章
如果你觉得本文写的还不错的话,期待留下一个小小的赞👍,你的支持是我分享的最大动力!
如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正
相关文章推荐
Linux进程学习【进程状态】
Linux进程学习【基本认知】
Linux工具学习之【gdb】
Linux工具学习之【git】
Linux工具学习之【gcc/g++】
Linux工具学习之【vim】
Linux 权限理解和学习