Linux进程(二)---进程的优先级和环境变量

我想在这先完成上一章的一个未说完的话题.最后一个我们讲到了僵尸进程,是指子进程已经结束,但是父进程还在运行没有来得及回收.此时这个子进程便是僵尸进程.

但是如果父进程运行完了,也没有回收就直接结束了,那这个子进程改由谁维护呢?

此时孤儿进程会被1号init进程领养,当然要由init进程回收。

这个尾巴说完了,我们开始进入正题:

目录

进程的优先级

基本概念

查看进程优先级

PRI 和 NI

如何调整进程的优先级

PRI和NI区别

其它概念

竞争性

独立性

并行

并发

上下文

环境变量

概念

问题引入

常见环境变量

PATH

查看环境变量方法

导入PATH环境变量

HOME

SHELL

和环境变量相关的命令

环境变量的组织方式

获取环境变量

通过代码获取环境变量

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

环境变量通常具有全局属性

命令行参数


进程的优先级

基本概念

1.CPU分配资源的的先后顺序,就是指进程的优先权。

2.优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能.

3.还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。

一句话:进程优先级是确认谁先得到资源,谁后得到资源.

那么为什么要有优先级呢?

本质是因为CPU有限,而进程太多.

进程太多,需要通过某种方式竞争资源.用例子来说:我们排队买票,军人可以享有优先权,普通人排队,这里军人的优先级就是比较高的.

在计算机中,我们可以用一些数据来表明优先级,只有优先级还不够,还得有评判,例如你在你们学校第一名,把你们放到孤岛上也没人在意你是年级第几,只有在学校,老师,领导才会根据这些成绩评判你,这样才有效.

这些评判优先级大小的叫做调度器.这个优先级便是我们的调度指标.优先级高的会先被调度到CPU执行.

查看进程优先级

先说结论:Linux下优先级具体的做法是:

优先级 = 老的优先级 + nice值.后面会说明这个.

我们先写一段程序.

 

然后老操作,一边执行,一边监视

 发现我们进程也会有两个属性,ps -al是显示更详细的进程信息.

其中PRI代表这个进程可被执行的优先级,其值越小越早被执行.

NI代表nice值.

 我们将分别介绍一下它们.

PRI 和 NI

关于PRI和NI,我们需要知道下面几个点.

1.PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,PRI值越小进程的优先级别越高.

2.NI就是我们所说的nice值了,其表示进程可被执行的优先级的修正数值.

3.PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice.

4.这样,当nice值为负值的时候,那么该进程将会优先级值将变小,即其优先级会变高,则其越快被执行
5.所以,调整进程优先级,在Linux下,就是调整进程nice值
6.nice其取值范围是-20至19,一共40个级别

如何调整进程的优先级

上面也说了,调整进程的优先级就是调整nice值.如何调整呢?

首先输入top指令,然后再按下‘r键.

 会出现这么一句话,提示你输入要修改nice值的进程.

 

 我们刚才运行进程的pid是23494,因此我们输入23494.

 之后让我们输入nice值,我们输入15,此时的进程优先级应为之前的80+15=95.

我们再来看一下:

 发现进程优先级确实如我们所想的,成为了95,NI值此时是我们调整的值15.

需要注意的是,每次调整都是以80为基准值开始调整,而不会受当前PRI值影响.

我们此时输入-15

 它不会95-15而变成80,而是从80开始,80-15=65.

这结果正如我们所说的. 

PRI和NI区别

PRI是进程的优先级,NI(nice)值是进程优先级的修正数据

进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。

其它概念

竞争性

竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级.

独立性

独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰.比如浏览器挂了不会影响qq的正常使用.子进程挂了不会影响父进程,父进程挂了不会影响子进程.

并行

并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行.

 

并发

并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发.

这里大家有没有这样一个疑惑:并发采用进程切换的方式,那如果这个进程没有执行完,你切换到别的进程了,那么下次再切回来这个进程的时候,它从哪开始呢?从头开始?那效率太低了吧,我们想的应该是从原来的位置开始,那么CPU是怎么知道上一次执行到哪了呢?

上下文

这里先说一个现象:如果进程A正在被运行,那么CPU的寄存器里面,一定保存的是进程A的临时数据!这些临时数据,称为A的上下文,包括函数最后一次返回值是什么,运行状态,运行位置等等.

所以当进程A暂时被切换下来的时候,需要进程A顺便带走自己的上下文数据,相当于保存到进程A中.

暂时保存的目的:一定是为了下次再拿出来,能恢复上去,就能按照之前的逻辑继续向后运行,就如同没有被中断过一样.

CPU内的寄存器只有一份,但是上下文有多份,分别对应不同的进程!每次寄存器只能读取一份上下文.

环境变量

概念

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

问题引入

大家有没有注意过这样的现象:

我们运行的自己写可执行程序需要加上./(即当前路径),而像ls,touch,rm这些命令执行的时候不需要加./ ,当然如果加上它的路径也可以.

 

 ls这些命令和我们写的唯一的不同点是:一个是我们自己写的,一个系统自带的命令,由于系统已经配置好了环境变量,所以才可以不用加路径直接运行.

现在知道这是环境变量的作用即可,后面讲完就会明白.

常见环境变量

PATH

查看环境变量方法
echo $PATH

 注意它们之间的路径是以:为分隔符.

当我们输入ls的时候,系统会先从第一个路径查找,如果有就直接执行,如果没有,继续向后查找,直至找到,如果找完了都没有,那么就会报错,command not found,命令没有找到.

所以想要我们的命令执行也可以不用加路径,我们可以把我们写的可执行程序写到这些PATH路径中,但是我们不建议这样做,因为会污染别人已经写好的命令池.

所以我们可以把我们写的放到环境变量中,相当于是单独一个.

导入PATH环境变量

输入指令:

export PATH=$PATH:/home/liqi/process

里面这个:后面的是你可执行文件的路径,可以使用pwd查看

然后我们再次查看环境变量.

 

发现已经成功导入了.

我们此时便可以直接运行process下的可执行程序了.

 

 当你退出登录重新进入的时候,环境变量又会初始化到最初的状态.

HOME

会记录显示当前用户的家目录.


所以之前说的cd ~,进入自己的家目录,实则是根据这个HOME进行的.

SHELL

显示当前的shell,通常是/bin/bash.

 

和环境变量相关的命令

1. echo: 显示某个环境变量值
2. export: 设置一个新的环境变量
3. env: 显示所有环境变量
4. unset: 清除环境变量
5. set: 显示本地定义的shell变量和环境变量

环境变量的组织方式

每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串

 

获取环境变量

通过代码获取环境变量

实际上,我们main函数有三个参数,int argc, char* argv[],这两个是命令行参数,稍后会讲.

char* env[]是环境变量参数.

这个是一个指针数组,就是我们上一部分的那张表.

我们可以写下面一段程序:

 

然后退出,make编译,然后运行

 

可以发现,这样就把所有的环境变量输出出来了. 

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

有两个接口:

putenv,是用来设置,后面会讲

getenv,获取环境变量.

例如我们想获得PATH环境变量.

输入代码:

 

然后make编译运行:

把PATH换成HOME:

 

同样地,也输出了出来. 

 我们有没有这么一个问题,是谁把这些环境变量导入到这些变量里呢?

其实是继承了父进程的环境变量,默认所有的环境变量都会被子进程继承。父进程正是我们的bash,这是一个简单的进程替换,后面会讲解.

这也另外说明了一个事实:环境变量具有全局属性

因为它可以被很多子进程拿到访问到.

环境变量通常具有全局属性

我们做个实验来证明它:

 我们把环境变量名改成了myenv.

可以发现什么都没有还出现了段错误.

此时我们再导入一个名为myenv的环境变量 .

export myenv="hello,world"

 此时bash已经有了myenv这个环境变量.而运行一个程序需要先创建一个子进程,子进程也会继承父进程.正是由于环境变量具有全局属性

此时我们再次make编译运行,便发现已经成功输出了这个环境变量.

这说明了两件事情:

1.子进程的环境变量是从父进程来的.

2.默认所有的环境变量都会被子进程继承(环境变量具有全局属性).

那么子进程的子进程也会继承子进程的环境变量

命令行参数

这个作为一个附加内容.

刚才我们讲解环境变量的时候说了,main()函数有三个参数,最后一个参数我们说了,那么还有前两个参数,这两个参数便叫做命令行参数.

我们写程序看看这是个什么东西.

 

 我们发现,它其实是把我们输入的选项作为参数传入到了argv中,具体有多少,是由argc决定的.

这些命令行参数这有什么意义呢?

最大的功能是:让同一个程序,通过不同的选项,使用不同的子功能!

例如ls -a,ls -a 或者ls -a -l都是如此.

这些内部都是命令行参数完成的.

或者我们自己实现一个简易的

会是如下的场景:

 

 所以这便是命令行参数的真正用法.

 

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

次元工程师!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值