[ Linux ] 进程优先级 和 环境变量

时间:2022-09-30 13:56:49

在上篇文章我们了解了进程的状态及Linux系统的进程状态,本篇我们主要了解进程优先级及环境变量。

1.进程优先级

说到优先级,我们首先要清楚什么是优先级,和权限有什么关系呢?

优先级是进程获取资源的先后顺序 ,而权限呢?谈的是能不能,比如:您是一名学生,您要去教室食堂吃饭,此时你是不能去的,因为你没有权限。 而优先级指的是您去学生食堂吃饭,但是可能人多,你需要排队,主要指的是先手顺序,但是一定能吃到饭。

为什么会存在优先级呢?

为什么您在食堂中吃饭需要排队呢?最主要的原因是因为资源不够,系统也是这样的。系统里面永远都是进程占大多数,而资源是少数!因此进程竞争资源是常态!存在竞争一定要确认先后,因此一定会存在优先级。

Linux下优先级的相关概念和操作

  1. cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  2. 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  3. 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

1.1 Linux下查看进程的优先级

我们首先模拟一段简单的c语言代码

#include <stdio.h>
#include <unistd.h>
int main()
{
while(1)
{
printf("hello PRI\n");
sleep(1);
}
return 0;
}

我们使用指令查看当前进程的优先级

ps -la

[ Linux ] 进程优先级 和 环境变量

在Linux进程优先级中由两部分组成:priority(PRI) + nice(NI)

默认的优先级是80,数字越小表示优先级越高,数字越大表示优先级越低

1.2 Linux 进程优先级的更改

要更改进程优先级,需要更改的不是pri,而是NI

PRI and NI

  1. PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。
  2. 那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。

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

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

我们使用top指令,再按r,此时系统就会提示让我们输入 PID ,输入我们要renice的PID,因此我们输入要修改的进程的PID

[ Linux ] 进程优先级 和 环境变量

此时输入pid后显示让我们输入新的nice的value,这里我们首先输入-100

[ Linux ] 进程优先级 和 环境变量

[ Linux ] 进程优先级 和 环境变量

这里提示我们没有权限,这是因为一个进程的优先级不能轻易修改,我们想要修改要使用root用户进行修改,我们切到root用户下完成以上操作。

[ Linux ] 进程优先级 和 环境变量


当我们完成以上操作后我们ctrl + C 退出top后,再次查看进程信息能够发现此时test的pri已经变成了60,而NI值是-20。可是不对呀,我们起始PRI为80,设置的NI为-100,不应该PRI成-20吗?哈哈哈,问出这个问题的同学可以自己想想,我们说进程PRI数字越小进程优先级越高,那你再小能小于0吗,小于0难道让操作系统还要倒贴你。因此操作系统规定NI的取值范围为[-20,19]。比如我们再次使用top,此时renice输入100,验证一下取值范围

ps -al

[ Linux ] 进程优先级 和 环境变量

[ Linux ] 进程优先级 和 环境变量

当我们输入100后,我们再次查看进程信息发现,NI的最大值确实为19,而且有一个现象是,PRI变成了99,而不是79。大家会疑惑,第一次我们renice -100时,PRI已经为60了,这里再加19不应该是79吗,为什么是99。这是现象说明了每次PRI值都会恢复为80。最终的PRI都是在80的基础上加上NI值。因此这里会显示99。

[ Linux ] 进程优先级 和 环境变量


总结:

  1. PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice 。
  2. 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行 。
  3. 所以,调整进程优先级,在Linux下,就是调整进程nice值 。
  4. nice其取值范围是-20至19,一共40个级别。
  5. 需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。
  6. 可以理解nice值是进程优先级的修正修正数据。

1.3 竞争 独立 并行 并发

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

2.环境变量

2.1 基本概念

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

2.2 环境变量的引入

首先我们继续使用刚才的c语言程序,现在有一个问题,我们为什么每次执行代码的时候,都要带上./ 为什么不能像基本指令一样直接执行呢?直接执行可执行程序会爆出命令找不到。而这就跟环境变量有关。系统中是存在相关的环境变量的,保存了程序的程序的搜索路径。

[ Linux ] 进程优先级 和 环境变量

Linux查看环境变量的方式是输入指令

env

[ Linux ] 进程优先级 和 环境变量

而win中也是存在环境变量的,在高级系统设置中我们就可以查看环境变量,如果配置过java环境的同学一定不陌生。

[ Linux ] 进程优先级 和 环境变量

而这里我们自己写的程序,为什么就找不到呢?

这是因为系统中搜索可执行程序的环境变量叫做PATH.

我们来查看一下PATH(每个人的PATH都可能不同)

env | grep PATH

[ Linux ] 进程优先级 和 环境变量

我们想要显示PATH的内容使用如下指令

echo $PATH

[ Linux ] 进程优先级 和 环境变量

这里环境变量PATH里面会承载多个路径,中间用 :作为分隔符,比如我们输入基本指令,系统会从PATH环境变量中一个路径一个路径进行查找,直到找到该指令或者不存在,此路径就作为改指令的搜索路径。其中ls等进本指令都在/usr/bin 路径下,而我们的myproc不在该路径下,因此当我们输入myproc的时候系统会提示找不到该指令

[ Linux ] 进程优先级 和 环境变量

2.3 环境变量的修改

如果我们就要输入myproc时运行该程序,我们有3中方法。

2.3.1 把可执行程序拷入系统路径中

我们要拷贝到系统路径要是用root权限,假设我们要将myproc拷入/usr/bin路径下

sudo cp myproc /usr/bin/

ls /usr/bin/myproc

[ Linux ] 进程优先级 和 环境变量

此时我们直接输入myproc,,就可以达到我们的目的

[ Linux ] 进程优先级 和 环境变量

但是我们不建议做,因为会污染Linux命令池

删除 之后,我们此时再运行发现查找不到了

sudo rm /usr/bin/myproc

[ Linux ] 进程优先级 和 环境变量


2.3.2 把当前所处的路径添加到环境变量

我们在进行这个操作前我们介绍一下我们在Linux命令行中定义的变量,可以定义本地变量,但是他并不会以环境变量的形式存在。

aaaa=123
echo $aaaa

[ Linux ] 进程优先级 和 环境变量


env | grep aaaa

[ Linux ] 进程优先级 和 环境变量


如果想让这个变量定义为环境变量我们要这样写,export叫做导出环境变量

export bbbb=123456
env | grep bbbb

[ Linux ] 进程优先级 和 环境变量

总结:

我们在命令行中定义的变量,第一种叫做普通变量。第二种叫做环境变量,环境变量具有全局属性。


此时我们会导环境环境变量了,我们将我们当前路径导入到环境变量中

pwd  查看当前环境变量
export PATH=$PATH:/home/Lxy/code/linux-code/9-28

[ Linux ] 进程优先级 和 环境变量

此时添加完之后,我们发现PATH路径添加了我们的myproc这条路径,之后我们输入myproc就可以直接运行程序了

[ Linux ] 进程优先级 和 环境变量


3.常见环境变量

接下来我们将着重介绍了解一下env下的环境变量

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

[ Linux ] 进程优先级 和 环境变量

history

[ Linux ] 进程优先级 和 环境变量

我们发现最大指令3000条

[ Linux ] 进程优先级 和 环境变量


user

[ Linux ] 进程优先级 和 环境变量


其他内容

[ Linux ] 进程优先级 和 环境变量


4.环境变量的获取

这里我们将介绍通过代码获取环境变量

4.1命令行的第三个参数

首先,大家知道main函数中有参数吗,有几个参数?

答案是有,有3个参数

首先我们先介绍main函数中的前两个参数,第一个参数是 argc 表示argv数组的个数。第二个参数是一个指针数组,这个数组里面放的什么呢?我们首先来看看结果[for循环初始化声明仅在c99下允许 因此编译时带上 -std=c99]

#include <stdio.h>
#include <unistd.h>
int main(int argc,char* argv[])
{
//char* argv[]:什么类型?里面放什么呢?
for(int i = 0; i < argc , ++i)
{
printf("argv[%d]:%s\n",i,argv[i]);
}

//printf("hello\n");
return 0;
}

[ Linux ] 进程优先级 和 环境变量

当我们进行命令行输入时,./myproc叫做可执行程序 -a -b -c -d等等这些叫做选项。这些都是字符串,都存在argv这个指针数组中。我们给main函数传递的argc,char* argv[],命令行参数传递的是命令行中输入的程序名和选项!!那意义是什么呢?

[ Linux ] 进程优先级 和 环境变量

我们知道了这两个参数 我们可以写一个最简单的计算器程序

#include <stdio.h>
#include <unistd.h>
#include <string.h>
// -a 加法
// -s 减法
int main(int argc,char *argv[])
{
if(argc != 4)
{
printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
return 0;
}
int x = atoi(argv[2]);
int y = atoi(argv[3]);
if(strcmp("-a", argv[1]) ==0)
{
printf("%d+%d=%d\n",x, y, x + y);
}
else if(strcmp("-s", argv[1]) ==0)
{
printf("%d-%d=%d\n",x, y, x - y);
}
else if(strcmp("-m", argv[1]) ==0)
{
printf("%d*%d=%d\n",x, y, x * y);
}
else if(strcmp("-d", argv[1]) ==0 && y != 0)
{
printf("%d/%d=%d\n",x, y, x / y);
}
else
{
printf("Usage: %s [-a|-s|-m|-d] one_data two_data\n", argv[0]);
}
return 0;
}

[ Linux ] 进程优先级 和 环境变量


意义:

因此,这两个参数最大的意义是同一个程序,通过传递不同的参数,让同一个程序有不同的执行逻辑,执行结果。这也是我们平时使用的 ls -a ls -l ,这就是Linux系统中会根据不同的选项,让不同的命令,有不同的表现,指令中那么多选项的由来和起作用的方式。

在win系统的也是存在这样的 cmd

[ Linux ] 进程优先级 和 环境变量


main的第三个参数

man函数是可以带第三个参数的!这第三个参数正是环境变量

int main(int argc,char *argv[],char *env[])
{
for(int i = 0;env[i];i++)
{
printf("env[%d]:%s\n",i,env[i]);
}
return 0;
}

[ Linux ] 进程优先级 和 环境变量

程序输出结果

[ Linux ] 进程优先级 和 环境变量

env查看环境变量

[ Linux ] 进程优先级 和 环境变量


结论:一个进程会被传入环境变量参数的!!


4.2 通过第三方变量environ获取

我们也可以使用第三方变量environ获取

我们可以通过man手册查看一下environ,是C语言给我提供的一个全局变量。

libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。

[ Linux ] 进程优先级 和 环境变量

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

[ Linux ] 进程优先级 和 环境变量


4.3 通过系统调用获取或设置环境变量

  • getenv
  • putenv
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
printf("%s\n",getenv("PATH"));
return 0;
}


[ Linux ] 进程优先级 和 环境变量


(本篇完)