在上篇文章我们了解了进程的状态及Linux系统的进程状态,本篇我们主要了解进程优先级及环境变量。
1.进程优先级
说到优先级,我们首先要清楚什么是优先级,和权限有什么关系呢?
优先级是进程获取资源的先后顺序 ,而权限呢?谈的是能不能,比如:您是一名学生,您要去教室食堂吃饭,此时你是不能去的,因为你没有权限。 而优先级指的是您去学生食堂吃饭,但是可能人多,你需要排队,主要指的是先手顺序,但是一定能吃到饭。
为什么会存在优先级呢?
为什么您在食堂中吃饭需要排队呢?最主要的原因是因为资源不够,系统也是这样的。系统里面永远都是进程占大多数,而资源是少数!因此进程竞争资源是常态!存在竞争一定要确认先后,因此一定会存在优先级。
Linux下优先级的相关概念和操作
- cpu资源分配的先后顺序,就是指进程的优先权(priority)。
- 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
- 还可以把进程运行到指定的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进程优先级中由两部分组成:priority(PRI) + nice(NI)
默认的优先级是80,数字越小表示优先级越高,数字越大表示优先级越低
1.2 Linux 进程优先级的更改
要更改进程优先级,需要更改的不是pri,而是NI
PRI and NI
- PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。
- 那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值。
用top命令更改已存在进程的nice:
进入top后按“r”–>输入进程PID–>输入nice值
我们使用top指令,再按r,此时系统就会提示让我们输入 PID ,输入我们要renice的PID,因此我们输入要修改的进程的PID
此时输入pid后显示让我们输入新的nice的value,这里我们首先输入-100
这里提示我们没有权限,这是因为一个进程的优先级不能轻易修改,我们想要修改要使用root用户进行修改,我们切到root用户下完成以上操作。
当我们完成以上操作后我们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
当我们输入100后,我们再次查看进程信息发现,NI的最大值确实为19,而且有一个现象是,PRI变成了99,而不是79。大家会疑惑,第一次我们renice -100时,PRI已经为60了,这里再加19不应该是79吗,为什么是99。这是现象说明了每次PRI值都会恢复为80。最终的PRI都是在80的基础上加上NI值。因此这里会显示99。
总结:
- PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice 。
- 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行 。
- 所以,调整进程优先级,在Linux下,就是调整进程nice值 。
- nice其取值范围是-20至19,一共40个级别。
- 需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。
- 可以理解nice值是进程优先级的修正修正数据。
1.3 竞争 独立 并行 并发
- 竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
- 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
- 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
- 并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发
2.环境变量
2.1 基本概念
- 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数。
- 如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在那里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
- 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。
2.2 环境变量的引入
首先我们继续使用刚才的c语言程序,现在有一个问题,我们为什么每次执行代码的时候,都要带上./ 为什么不能像基本指令一样直接执行呢?直接执行可执行程序会爆出命令找不到。而这就跟环境变量有关。系统中是存在相关的环境变量的,保存了程序的程序的搜索路径。
Linux查看环境变量的方式是输入指令
env
而win中也是存在环境变量的,在高级系统设置中我们就可以查看环境变量,如果配置过java环境的同学一定不陌生。
而这里我们自己写的程序,为什么就找不到呢?
这是因为系统中搜索可执行程序的环境变量叫做PATH.
我们来查看一下PATH(每个人的PATH都可能不同)
env | grep PATH
我们想要显示PATH的内容使用如下指令
echo $PATH
这里环境变量PATH里面会承载多个路径,中间用 :作为分隔符,比如我们输入基本指令,系统会从PATH环境变量中一个路径一个路径进行查找,直到找到该指令或者不存在,此路径就作为改指令的搜索路径。其中ls等进本指令都在/usr/bin 路径下,而我们的myproc不在该路径下,因此当我们输入myproc的时候系统会提示找不到该指令
2.3 环境变量的修改
如果我们就要输入myproc时运行该程序,我们有3中方法。
2.3.1 把可执行程序拷入系统路径中
我们要拷贝到系统路径要是用root权限,假设我们要将myproc拷入/usr/bin路径下
sudo cp myproc /usr/bin/
ls /usr/bin/myproc
此时我们直接输入myproc,,就可以达到我们的目的
但是我们不建议做,因为会污染Linux命令池
删除 之后,我们此时再运行发现查找不到了
sudo rm /usr/bin/myproc
2.3.2 把当前所处的路径添加到环境变量
我们在进行这个操作前我们介绍一下我们在Linux命令行中定义的变量,可以定义本地变量,但是他并不会以环境变量的形式存在。
aaaa=123
echo $aaaa
env | grep aaaa
如果想让这个变量定义为环境变量我们要这样写,export叫做导出环境变量
export bbbb=123456
env | grep bbbb
总结:
我们在命令行中定义的变量,第一种叫做普通变量。第二种叫做环境变量,环境变量具有全局属性。
此时我们会导环境环境变量了,我们将我们当前路径导入到环境变量中
pwd 查看当前环境变量
export PATH=$PATH:/home/Lxy/code/linux-code/9-28
此时添加完之后,我们发现PATH路径添加了我们的myproc这条路径,之后我们输入myproc就可以直接运行程序了
3.常见环境变量
接下来我们将着重介绍了解一下env下的环境变量
- PATH : 指定命令的搜索路径
- HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
- SHELL : 当前Shell,它的值通常是/bin/bash。
history
我们发现最大指令3000条
user
其他内容
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;
}
当我们进行命令行输入时,./myproc叫做可执行程序 -a -b -c -d等等这些叫做选项。这些都是字符串,都存在argv这个指针数组中。我们给main函数传递的argc,char* argv[],命令行参数传递的是命令行中输入的程序名和选项!!那意义是什么呢?
我们知道了这两个参数 我们可以写一个最简单的计算器程序
#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;
}
意义:
因此,这两个参数最大的意义是同一个程序,通过传递不同的参数,让同一个程序有不同的执行逻辑,执行结果。这也是我们平时使用的 ls -a ls -l ,这就是Linux系统中会根据不同的选项,让不同的命令,有不同的表现,指令中那么多选项的由来和起作用的方式。
在win系统的也是存在这样的 cmd
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;
}
程序输出结果
env查看环境变量
结论:一个进程会被传入环境变量参数的!!
4.2 通过第三方变量environ获取
我们也可以使用第三方变量environ获取
我们可以通过man手册查看一下environ,是C语言给我提供的一个全局变量。
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。
#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]);
}
4.3 通过系统调用获取或设置环境变量
- getenv
- putenv
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char *argv[])
{
printf("%s\n",getenv("PATH"));
return 0;
}
(本篇完)
标签:优先级,int,argv,环境变量,Linux,进程,我们 From: https://blog.51cto.com/xingyuli/5719136