进程优先级
1.什么的优先级
概念:指定进程获取某种资源(CPU)的先后顺序
本质:优先级的本质是优先级数字的大小,Linux中优先级数字越小,优先级越高
task_struct 进程控制快-> struct -> 内部字段 -> int prio = ??
default_prio = 80;
nice = ??
优先级vs权限
优先级:已经能做了,是我们获取资源的顺序
权限:能不能做的问题
2.为什么要有优先级
- 进程访问的资源(CPU)始终都是有限的,系统中进程大部分情况都是比较多的。
- 操作系统关于调度和优先级的原则:采用分时操作系统,保证基本的公平,如果进程因为长时间不被调度,就造成了饥饿问题。
3.Linux的优先级特点和查看方式
-
特点
- PRI:进程优先级
- NI:进程优先级的修正数据,nice值
- UID:代表执行者的身份
- PID:代表这个进程的代号
- PPID:代表这个进程是由哪个进程发展衍生而来的,也就是父进程的代号
🐂:新的优先级 = 优先级 + nice ,可以达到对于进程优先级动态修改的过程
- nice并不能容易调整,而是有范围的!->[-20 19] ----40个数字(在后面的地址空间再谈)
- 每次调整优先级,都是从80开始的
-
查看方式
用top命令更改已存在进程的nice:
- top
- 进入top后按"r" -> 输入进程PID -> 输入nice值
命令行参数和环境变量
命令行参数
C语言中,我们以前会接触到下面这种写法
- 带这些参数的意义的什么呢?
- 可以看出,数组argv就像一个选项,当我们输入什么选项时,bash会根据该选项去匹配对应的进程。
- 注:默认是输入给父进程bash的
1、为什么要这么干呢?
本质:命令行参数本质上交给我们程序的不同选项,用来制定不同的程序功能。命令中会携带很多的选。
就像我们经常用的命令一样->举例:ls,ls -a,ls -l这些不同的选项会显示出不同的特性
2、谁干的?
- 父进程bash
命令行中启动的程序,都会变成进程,其实都是bash的子进程。
环境变量
1、直接看现象
为什么我们输入系统的这些命令不用带 ./ ,而是直接输入命令就可以直接执行,而我们自己的可执行程序就需要指明当前路径呢?
- 这些命令本质就是一个可执行程序,依照上面提到的命令行参数表,可以带各种不同的选项
- 表明,在Linux中,存在一些全局的设置,告诉命令行解释器,应该去那些路径下寻找可执行程序
这里,我们引入一个环境变量:PHTH
👵概念
在操作系统中用来指定操作系统运行环境的一些参数
🙏查看环境变量方法
- echo &name name:你的环境变量名称
- 在系统中很多的设置,在我们登录Linux系统的时候,就已经被加载到了bash进程中(内存)
- 当bash在执行命令的时候,需要先找到命令,然后再执行,而上面这个路径下的命令,是bash执行命令时的默认寻找路径,如果没指定,就会自动到这个路径下寻找,如果没找到,就会报错,这就是为什么上面我们要指定当前命令,而系统这些自带的命令不用指定当前命令。
🐔设置环境变量的方法
通过这种方法,我们的可执行程序也可以像系统默认的命令一样使用,而不要指定当前路径。
- 当我们重新打开程序时,我们可以看到
表明默认我们修改的环境变量都是内存级别的,则最开的环境不是在内存中的,而是在系统的对应配置文件。
🧍♀️配置文件在哪里呢?
- 在root路径下,存在着上面四种关于bash的文件,而.bash_profile中如果我们添加配置,则在电脑重启的时候也不会清空,因为此时修改的环境变量是在配置文件中进行的。
2、常见的环境变量
- PATH:指定命令的搜索路径
- HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
- SHELL:当前的shell,它的值通常是/bin/bash。
🍋测试HOME
🐂与环境变量相关的命令
- echo:显示某个环境变量值
- export:设置一个新的环境变量
- env:显示所有环境变量
- unset:清除环境变量
- set:显示本地定义的shell变量和环境变量
3、整体理解环境变量
a、代码
- bash进程在启动时,默认会给子进程形成环境变量表。
b、理解
- 环境变量具有系统的全局属性,因为环境变量本身会被紫禁城继承下去。
如图:这个变量是存在的,但是我们查看环境变量的时候不会显示出来,这种变量叫做本地变量
本地变量只在本bash内部有效,无法被子进程继承下去,导成环境变量,此时才能被子进程获取。
进程的地址空间
1、直接看代码,看现象
由图可以看出,父子进程是具有独立性的。
进程 = 内核数据结构(task_struct) + 代码和数据
为什么地址不变,而当子进程中的g_val变成300的时候,父进程的g_val还是100呢?
我们发现,父子进程,输出地址是一致的,但是变量内容不一样!能得出如下结论:
- 变量内容不一样,所以父子进程输出的变量绝对不是同一个变量
- 但地址值是一样的,说明,该地址绝对不是物理地址!
- 在Linux地址下,这种地址叫做 虚拟地址
- 我们在用C/C++语言所看到的地址,全部都是虚拟地址!物理地址,用户一概看不到,由OS统一管理
- OS必须负责把虚拟地址转变成物理地址
2、引入最基本的理解
父进程和子进程都分别有其自己的一个虚拟地址空间,当用虚拟地址访问数据的时候,OS通过页表的查找找到对应的物理地址。
这里也就涉及到了一个概念:写时拷贝
OS会自助完成写时拷贝,进行按需申请,但父进程和子进程仅仅只是访问同一个数据而不修改的时候,两个进程此时指向的确实是同一个物理空间,但当需要进行修改的时候,OS会进行该数据的拷贝,并把需要修改的进程指向该拷贝的空间
意义:通过调整拷贝的时间顺序,达到有效节省空间的目的。
3、地址空间的意义
如果没有地址空间,数据写入物理内存的时候地址会是乱的,此时要访问特定的数据就会很麻烦,CPU的效率将会折扣,而如果有了地址空间,每次写入数据时只关注地址空间就行,而取出数据时,把相对应的地址空间加载到内存中,OS对该地址空间的访问可以迅速拿到想要的数据,而无需去遍历整个物理内存。
- 讲无序变成有序,让进程以统一的视角看待物理内存以及自己运行的各个区域!
- 进程管理模块和内存管理模块进行解耦
- 拦截非法请求->对物理内存进行保护
页表的意义
OS在通过页表进行访问物理地址时,页表会进行一系列的检查
- 数据是不是不在物理内存中 -> 缺页中断
- 数据是不是需要写时拷贝 -> 发生写时拷贝
- 如果都不是,才进行异常处理
Linux真正是如何的调度的?
上面我们提到,nice值并不能让你任意调整,而是有范围的![-20,19] --- 40个数字
- Linux系统每一个CPU都有一个运行队列
- Linux采用分时操作系统,为了保证公平
- 其实nice可以修改的这40个nice值对应的是运行队列中queue队列中的[100,139]
- 这里的bitmap数组大小为什么是5,是因为在32位机器下,32*5=160>140,满足所需要的位数。
理解
- 在CPU找进程的时候,runqueue会有两个队列,一个表示活跃的队列,一个表示过期的队列,通用这两个队列的转换,就可以实现对进程优秀级大小不同的实现快慢。
- CPU查看*active是否位空,如果不为空,说明里有进程需要执行,如果有,就遍历从100到139这个区级的进程,根据优先级找到里面需要执行的进程
- 如果因为某种原因(时间片到了等等)导致该进程暂时先停止然后去执行其他进程,那么该进程的数据就会拷贝到过期的队列中,然后把活跃中该进程删除
- 等到把活跃队列所有进程都删除之后,就交换活跃队列和过期队列的地址,过期队列变成活跃队列,活跃队列变成过期队列,再重复以上过程
- 等到OS检查*active为空时,说明此时没有进程需要执行。