目录
1.进程优先级
1.1 基本概念
1.2 查看系统进程
1.3 修改进程优先级的命令
2.进程间切换
2.1 相关概念
2.2 Linux2.6内核进程调度队列(了解即可)
3.命令行参数
我们知道进程在内存中是需要排队的,比如运行队列,等待队列。那排队是干什么的:就是在确认优先级,来确定得到某种资源的先后顺序。为什么要确认优先级,本质就是资源不足。那么操作系统是怎么做到呢?我们下面讲解:
优先级其实就是PCB中的一个 int 字段,数值越小,优先级越大,跟我们的考试排名一样。Linux进程的优先级数值范围:60~99。Linux中默认进程的优先级都是80。
我们先编写一段代码
在linux或者unix系统中,用ps -la 命令则会类似输出以下几个内容:
我们很容易注意到其中的几个重要信息,有下:
PRI and NI:
PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高
那NI就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice。pri(old) ,都是从80开始的!
这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行所以,调整进程优先级,在Linux下,就是调整进程nice值
nice其取值范围是-20至19,一共40个级别。nice调整最小是:-20,超过部分统一当成-20。nice调整最大是:19,超过部分统一当成19。
PRI vs NI:
- 需要强调一点的是,进程的nice值不是进程的优先级,他们不是一个概念,但是进程nice值会影响到进程的优先级变化。可以理解nice值是进程优先级的修正修正数据
用top命令更改已存在进程的nice:
- top
- 进入top后按“r”–>输入进程PID–>输入nice值
我们输入进程号讲 nice 改为19
普通用户是没有办法将优先级调大,让PRI减小的。需要使用su换成root,或使用sudo命令。
因为要并发,所以必定要考虑进程间切换。
每一个进程不是占有CPU就一直运行,每隔一段时间,会自动被操作系统从cpu上剥离下来。Linux内核是支持进程之间进行cpu资源抢占的!是基于时间片的轮转式抢占式内核。
为什么我们函数内定义的栈临时变量,会返回给外部,我们的程序/进程,它怎么知道我们当前运行到哪里里?如何做到函数间跳转? 因为cpu内存在大量寄存器,比如eip是程序计数器或者叫pc,会自动执行我们要执行的下一行代码。我们的进程在运行的时候,是会使用这些寄存器的,我们的进程,会产生各种数据,在寄存器中临时保存。
如果我们有多个进程呢?各个进程在CPU寄存器中形成的临时数据,都应该是不一样的!而cpu内寄存器只有一套,我们如何做到让每个进程使用cpu时能从上次时间片执行到的位置继续执行?我们可以先简单的理解为时间片结束后,cpu寄存器中的数据会先保存到进程PCB中,然后下次执行时先读取PCB中存储的寄存器的数据,然后继续执行,本质就是将CPU寄存器的内容,保存到内存中!
上图是Linux2.6内核中进程队列的数据结构,之间关系也已经给大家画出来,方便大家理解
一个CPU拥有一个runqueue
优先级
活动队列
1. 从0下表开始遍历queue[140]
2. 找到第一个非空队列,该队列必定为优先级最高的队列
3. 拿到选中队列的第一个进程,开始运行,调度完成!
4. 遍历queue[140]时间复杂度是常数!但还是太低效了!
过期队列
active指针和expired指针
总结
在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不随着进程增多而导致时间成本增加,我们称之为进程调度O(1)算法
命令行参数是什么?
我们看下面一段代码看下面一段代码
#include
#include
#include
int main(int argc, char *argv[])
{
int i = 0;
for(;i
运行输出:
可以发现main函数是可以传参的,shell 会自动讲命令行输入的一大串字符,按空格分割成小的字串,第一参数argc存命令行字串个数,第二个参数argc是一个指针数组存字串内容。
命令行参数,可以支持各种指令级别的命令行选项的设置!这样就可以理解之前学的指令,选项是什么关系了。
我们来模拟实现一个计算器
#include
#include
#include
int main(int argc, char *argv[])
{
if(argc != 4)
{
printf("Use error\nUsage: %s op[-add|sub|mul|div] d1 d2\n",argv[0]);
return 1;
}
// 你的程序一定有4个命令行参数,第一个是程序名
int x = atoi(argv[2]);
int y = atoi(argv[3]);
if(strcmp(argv[1],"-add")==0)
{
int result = x+y;
printf("%d+%d=%d\n",x,y,result);
}
else if(strcmp(argv[1],"-sub")==0)
{
int result = x-y;
printf("%d-%d=%d\n",x,y,result);
}
else if(strcmp(argv[1],"-mul")==0)
{
int result = x*y;
printf("%d*%d=%d\n",x,y,result);
}
else if(strcmp(argv[1],"-div")==0)
{
if(0==y)
{
printf("%d/%d=error! div zero\n",x,y);
}
else
{
int result = x/y;
printf("%d/%d=%d\n",x,y,result);
}
}
else
{
printf("Use error,you should use the right command line\nUsage: %s op[-add|sub|mul|div] d1 d2\n",argv[0]);
}
return 0;
}
运行结果:
对于为什么系统命令不用加 ./指定位置 ,而我们写的程序就需要写 ./ ,这就涉及到环境变量了,下一篇文章我们讲解环境变量。
本篇结束!