赞
踩
什么是优先级?
为什么要有优先级
操作系统关于调度和优先级的原则:分时操作系统,基本的公平,如果进程因为长时间不被调整,就造成了饥饿问题
ps -lA
其中PRI值越低优先级越高
因为PRI值是由操作系统内核动态调整的,我们无法直接去调整这个值,所以我们必须通过nice值去调整它。nice值就是上图PRI后面NI。
因为PRI是系统内核去动态调整的,我们修改后需要经过内核的允许,如果这个PRI值超过了内核的最大限度,那么这个值就会保留在临界值。
我们的计算公式为:新的PRI = 进程默认PRI + nice值,这个nice值有正负数,我们可以举一个例子:一个进程的PRI为80,我们给NI值为-10,再根据上面的公式得出新的PRI为70
#include<stdio.h>
int main()
{
while(1){
}
return 0;
}
我们可以通过下面的命令进行修改
number为想要的nice值,PID为要操作的进程
renice [number] [PID]
70
,NI是-10
假设cpu处理一个进程的时间为1秒,那么1个cpu处理99个进程的时间就是99秒。但是当有一台拥有3个cpu的计算机处理这99个进程时,只需要33秒。这就是并行,多个cpu同时处理多个进程。
如何切换?
被保存起来的上下文会存储到系统内核中,等待任务重新调度执行时再次加载进来。
CPU 的上下文切换分三种:进程上下文切换、线程上下文切换、中断上下文切换。
在我们运行程序的时候,需要知道此程序在哪个位置
在Linux的中的命令,它为什么不需要指定路径来执行呢?是因为有个叫【PATH】的环境变量,在我们输入指令后,会在指定路径下查找,如果找不到要执行的指令就会返回错误【command not found】
echo $PATH
/usr/bin
目录,那么我们写的这个程序也就可以拷贝到这个目录下就可以不指定路径直接执行了export PATH=路径
export PATH=$PATH:路径
那么为什么新开了一个终端它就又恢复了呢?
那么这个配置文件在哪?
.bash_profile # 当前登录用户环境变量
.bashrc # 当前登录用户环境变量
/etc/bashrc # 全局环境变量
env
环境变量是随着启动操作系统时生成的,也就是说,环境变量是属于bash的。
指令是一个程序,在bash上执行,那么这个程序就是bash的子进程
我们平时所用的pwd命令就是有一个环境变量叫pwd,这个环境变量存储着用户当前的所在位置
我们也可以自己实现一个pwd指令
在实现的时候需要了解一个函数getenv,我们用man手册查看一下
#include<stdio.h>
#include<stdlib.h>
int main()
{
char* ret = getenv("PWD");
printf("%s\n",ret);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[], char* environ[])
{
return 0;
}
getenv()
。#include <stdio.h> #include <string.h> int main(int argc,char* argv[]) { if(argc < 2) { printf("指令参数太少!\n"); return 1; } if(strcmp(argv[1],"-a")==0) { printf("执行-a\n"); } else if(strcmp(argv[1],"-b")==0) { printf("执行-b\n"); } else { printf("指令有误!\n"); } return 0; }
#include <stdio.h>
#include <string.h>
int main(int argc,char* argv[])
{
printf("%d\n",argc);
int i=0;
for(i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
return 0;
}
从上面 可以看出 [argc]是存储指令参数的个数的(包括指令),[char* argv[]]这个指针数组是存储指令参数的(包括指令)
对于第三个参数,是一个指针数组,存储的是各个环境变量的内容,因为这些内容是字符串常量,而表示字符串常量通常使用其首字符地址
我们是很少使用第三个参数的,因为这个数组存储了所有的环境变量,想要找到特定的环境变量还是挺困难的,那么我们使用这段代码,证明第三个参数存储了环境变量:
#include <stdio.h>
#include <string.h>
int main(int argc,char* argv[],char* environ[])
{
int i = 0;
for(i = 0; environ[i]; i++)
{
printf("[%d]-->%s\n",i, environ[i]);
}
return 0;
}
#include <stdio.h>
#include <string.h>
int main(int argc,char* argv[])
{
extern char** environ;
int i=0;
for( i=0;environ[i];i++)
{
printf("[%d]-->%s\n",i,environ[i]);
}
return 0;
}
环境变量是具有全局属性的,也就意味着子进程只能继承父进程的具有全局属性的环境变量。称作本地变量。如何设置本地变量呢?我们只需要在bash上面按这个格式敲指令:
变量中间不能有空格
[变量名]=[内容]
我们发现使用env来查看我们设置的变量,并不能显示出结果,证明了我们刚刚设置的变量是本地变量
但是使用【echo】命令还可以查看到,因为echo是可以操作环境变量的,所用echo命令是可以操作所有的变量的,不管是本地变量还是环境变量。
子进程并没有继承父进程的本地变量,那我们如何使本地变量变成环境变量呢?我们输入下面这个指令:
export [变量名称]
set
unset [变量名]
如果有多个CPU就要考虑进程个数的父子均衡问题。
queue下标说明:
我们进程的都是普通的优先级,前面说到nice值的取值范围是-20~19,共40个级别,依次对应queue当中普通优先级的下标100~139。
注意: 实时优先级对应实时进程,实时进程是指先将一个进程执行完毕再执行下一个进程,现在基本不存在这种机器了,所以对于queue当中下标为0~99的元素我们不关心。
时间片还没有结束的所有进程都按照优先级放在活动队列当中,其中nr_active代表总共有多少个运行状态的进程,而queue[140]数组当中的一个元素就是一个进程队列,相同优先级的进程按照FIFO规则进程排队调度。
调度过程如下:
bitmap[5]:queue数组当中一共有140个元素,即140个优先级,一共140个进程队列,为了提高查找非空队列的效率,就可以用5 × \times× 32个比特位表示队列是否为空,这样一来便可以大大提高查找效率。
总结: 在系统当中查找一个最合适调度的进程的时间复杂度是一个常数,不会随着进程增多而导致时间成本增加,我们称之为进程调度的O(1)算法。
由于活动队列上时间片未到期的进程会越来越少,而过期队列上的进程数量会越来越多(新创建的进程都会被放到过期队列上),那么总会出现活动队列上的全部进程的时间片都到期的情况,这时将active指针和expired指针的内容交换,就相当于让过期队列变成活动队列,活动队列变成过期队列,就相当于又具有了一批新的活动进程,如此循环进行即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。