目录
- 一、进程的优先级
- 1.1 基本概念
- 1.2 查看进程优先级
- 1.3 PRI&NI
- 1.4 如何更改进程的优先级
- 1.4.1 用top命令更改进程的nice
- 1.4.2 用renice命令更改进程的nice
- 1.5 其他概念
- 二、环境变量
- 2.1 基本概念
- 2.2 常见的环境变量
- 2.3 查看环境变量
- 2.3.1 测试PATH
- 2.3.2 测试HOME
- 2.3.3 测试SHELL
- 2.4 和环境变量相关的命令
- 2.4.1 echo命令
- 2.4.2 export命令
- 2.4.3 env命令
- 2.4.4 set命令
- 2.4.5 unset命令
- 2.5 环境的组织方式
- 2.6 通过代码获取环境变量
- 2.6.1 main函数命令行参数的了解
- 2.6.2 main函数的环境变量获取
- 2.6.3 通过第三方变量environ获取
- 2.7 通过系统调用获取环境变量(常用)
一、进程的优先级
1.1 基本概念
- CPU资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权高的进程有优先执行权力。配置进程优先权对多任务环境的Linux很有用,可以改善系统性能。
- 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
为什么要有优先级?
就是因为CPU是有限的!进程太多,需要通过某种方式竞争资源!
什么是优先级?
确认是谁应该先获得某种资源,谁后获得。 我们是可以用一些数据表明优先级的!
**Linux具体的优先级做法:**优先级=老的优先级+nice值。
1.2 查看进程优先级
在Linux或者Unix操作系统中,用ps -l命令会类似输出以下几个内容:
[zl@VM-16-2-centos lesson13]$ ps -l
当我们创建一个进程后,我们可以使用 ps -la命令查看该进程优先级的信息
[zl@VM-16-2-centos lesson13]$ ps -la
注意;在Linux操作系统中,初始进程一般优先级PRI默认为80,NI默认为40。
列出的信息当中有几个重要的信息,如下:
- UID:代表执行者的身份
- PID:代表这个进程的代号
- PPID:代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
- PRI:代表这个进程可被执行的优先级,其值越小越早被执行
- NI:代表这个进程的nice值
1.3 PRI&NI
- PRI代表进程的优先级(priority),通俗点说就是进程被CPU执行的先后顺序,该值越小进程的优先级别越高。
NI代表的是nice值,其表示进程可被执行的优先级的修正数值。
PRI值越小越快被执行,当加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+NI。
若NI值为负值,那么该进程的PRI将变小,即其优先级会变高。
调整进程优先级,在Linux下,就是调整进程的nice值。
NI的取值范围是-20至19,一共40个级别。
注意:在Linux操作系统当中,PRI(old)默认为80,即PRI=80+NI。
需要强调的一点是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响进程的优先级变化。
可以理解nice值是进程优先级的修正数据。
1.4 如何更改进程的优先级
1.4.1 用top命令更改进程的nice
top命令就相当于Windows操作系统中的任务管理器,它能够动态实时的显示系统当中进程的资源占用情况。
使用top命令后按“r”键,会要求你输入待调整nice值的进程PID
输入进程PID并回车后,会要求你输入调整后的nice值。
输入nice值后按“q”即可退出,如果我们这里输入的nice值为20,那么此时我们再用ps命令查看进程的优先级信息,即可发现进程的NI变成了19,PRI变成了99(80+NI-1)。
注意:若是想将NI值调为负值,也就是将进程的优先级调高,需要使用sudo命令提升权限(sudo top)。
1.4.2 用renice命令更改进程的nice
使用renice命令,后面跟上更改后的nice值和进程的PID即可。
之后我们再用ps命令查看进程的优先级信息,也可以发现进程的NI变成了20,PRI变成了99(80+NI-1)
注意:若是想使用renice命令将NI值调为负值,也需要使用sudo命令提升权限(sudo renice)。
1.5 其他概念
- 竞争性:系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便有了优先级。
- 独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰。
- 并行:多个进程在多个CPU下分别同时进行运行,这称之为并行。
- 并发:多个进程在一个CPU下采用进程切换的方式,在一段时间内,让多个进程都得以推进,称之为并发。
切换:
如果进程A正在被运行,CPU内的寄存器里面,一定保存的是进程A的临时数据!
寄存器中的临时数据,叫做A的上下文!
上下文数据可以被丢弃吗?绝对不可以!
当进程A暂时被切下来的时候,需要进程A顺便带走自己的上下文数据!
带走暂时保存的目的:就是为了下次回来的时候,能恢复上去,就能继续按照之前的逻辑继续向后运行,就如同没有被中断过一样。
CPU内的寄存器只有一份,但是上下文可以有多份,分别对应不同的进程!
二、环境变量
2.1 基本概念
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
例如,我们编写的C/C++代码,在各个目标文件进行链接的时候,从来不知道我们所链接的动静态库在哪里,但是按照可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
环境变量通常具有某些特殊用途,并且在系统当中通常具有全局特性。
子进程的环境变量是从父进程来的!
默认,所有的环境变量,都会被子进程继承,环境变量具有全局属性
2.2 常见的环境变量
- PATH:指定命令的搜索路径。
- HOME:指定用户的主工作目录(即用户登录到Linux系统中的默认所处目录)
- SHELL:当前Shell,它的值通常是/bin/bash
2.3 查看环境变量
我们可以通过echo命令来查看环境变量,方法如下:
echo $NAME //NAME为待查看的环境变量名称
例如,查看环境变量PATH。
echo $PATH
2.3.1 测试PATH
有没有想过一个问题:为什么执行ls命令的时候不用带./就可以执行,而我们自己生成的可执行程序必须要在前面带上./才可以执行?
容易理解的是,要执行一个可执行程序必须要先找到它在哪里,既然不带./就可以执行ls命令,说明系统能够通过ls名称找到ls的位置,而系统是无法找到我们自己的可执行程序的,所以我们必须带上./,以此告诉系统该可执行程序位于当前目录下。
而系统就是通过环境变量PATH来找到ls命令的,查看环境变量PATH我们可以看到如下内容:
可以看到环境变量PATH当中有多条路径,这些路径由冒号隔开,当你使用ls命令时,系统就会查看环境变量PATH,然后默认从左到右依次在各个路径当中进行查找。
而ls命令实际就位于PATH当中的某一个路径下,所以就算ls命令不带路径执行,系统也是能够找到的。
那可不可以让我们自己的可执行程序也不用带路径就可以执行呢?
方式一:将可执行程序拷贝到环境变量PATH的某一路径下。
既然在未指定路径的情况下系统会根据环境变量PATH当中的路径进行查找,那我们就可以将我们的可执行程序拷贝到PATH的某一路径下,此后我们的可执行程序不带路径系统也可以找到了。
sudo cp proc /usr/bin
方式二:将可执行程序所在的目录导入到环境变量PATH当中
将可执行程序所在的目录导入到环境变量PATH当中,这样一来,没有执行路径时系统就会来到该目录下进行查找了。
export PATH=$PATH:/home/zl/lesson13
将可执行程序所在的目录导入到环境变量PATH当中后,位于该目录下的可执行程序也就可以在不带路径的情况下执行了。
2.3.2 测试HOME
任何一个用户在运行系统登录时都有自己的主工作目录(家目录),环境变量HOME当中即保存的该用户的主工作目录。
超级用户
普通用户
2.3.3 测试SHELL
我们在Linux操作系统当中所敲的各种命令,实际上需要由命令行解释器进行解释,而在Linux当中有许多种命令行解释器(例如bash、sh),我们可以通过查看环境变量SHELL来知道自己当前所用的命令行解释器的种类。
而该命令行解释器实际上是系统当中的一条命令,当这个命令运行起来变成进程后就可以为我们进行命令行解释。
2.4 和环境变量相关的命令
2.4.1 echo命令
这个处理可以查看相关的环境变量,还可以直接打印一些数据
2.4.2 export命令
设置一个新的环境变量,还可以将本地变量导出环境变量;所谓的本地变量就相当于我们在C/C++种定义一个变量
2.4.3 env命令
显示所有环境变量
2.4.4 set命令
显示本地定义的shell变量和环境变量
2.4.5 unset命令
清除环境变量;处理环境变量外,还有本地变量,所谓的本地变量就相当于我们在C/C++种定义一个变量
部分环境变量说明
环境变量名称 | 表示内容 |
---|---|
PATH | 命令的搜索路径 |
HOME | 用户的主工作目录 |
SHELL | 当前Shell |
HOSTNAME | 主机名 |
TERM | 终端类型 |
HISTSIZE | 记录历史命令的条数 |
SSH_TTY | 当前终端文件 |
USER | 当前用户 |
邮箱 | |
PWD | 当前所处路径 |
LANG | 编码格式 |
LOGNAME | 登录用户名 |
2.5 环境的组织方式
在系统当中,环境变量的组织方式如下:
每个程序都会收到一张环境变量表,环境表是一个字符指针数组,每个指针指向一个以‘\0’结尾的环境字符串,最后一个字符指针为空。
2.6 通过代码获取环境变量
2.6.1 main函数命令行参数的了解
你知道main函数其实是有参数的吗?
main函数其实有三个参数,只有我们平时基本不用它们,所以一般情况下都没有写出来。
int main(int arge, char* argv[], char* envp[])//这里的三个参数就是命令行参数
{}
我们可以在Windows下的编译器进行验证,当我们调试代码的时候,若是一直使用逐步调试,那么最终会来到调用main函数的地方。
在Linux操作系统下,编写以下代码,生成可执行程序并运行。
运行结果如下
现在说说main函数的前两个参数,main函数的第二个参数是一个字符指针数组,数组当中的第一个字符指针存储的是可执行程序的位置,其余字符指针存储的是所给的若干选项,最后一个字符指针为空,而main函数的第一个参数代表的就是字符指针数组当中的有效元素个数。
通过该程序可以观察到,使用main函数的前面两个参数可以实现,同一个命令的不同选项的功能(例如ls -a,ls-l)。
2.6.2 main函数的环境变量获取
main函数的第三个参数接收的实际上就是环境变量表,我们可以通过main函数的第三个参数来获取系统的环境变量。
例如,编写以下代码,生成可执行程序并运行。
运行结果就是各个环境变量的值:
2.6.3 通过第三方变量environ获取
除了使用main函数的第三个参数来获取环境变量以外,我们还可以通过第三方变量environ来获取。
运行该代码生成的可执行程序,我们同样可以获得环境变量的值。
注意:libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所有在使用时要用extern进行声明。
2.7 通过系统调用获取环境变量(常用)
除了通过main函数的第三个参数和第三方变量environ来获取环境变量外,我们还可以通过系统调用getenv函数来获取环境变量。
getenv函数可以根据所给环境变量名,在环境变量表当中进行搜索,并返回一个指向相应值得字符串指针。
例如:使用getenv函数获取环境变量PATH的值。
运行结果: