最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

14 进程调度

来源:博客园

进程调度的原因:

一是CPU同一时刻只能运行一个进程,并且CPU 的个数总是少于进程个数,就需要让进程共用一个CPU;二是当一个进程拿不到资源时就应该让出CPU,否则会一直霸占CPU;


(资料图)

1、管理进程:

进程的生命周期:

进程的状态:运行、睡眠、等待、新建、僵死;

组织进程:

设计思想:链表数据结构,一个优先级对应一个链表头;

schedclass_t 结构是一个总的全局结构,其中包含一个schdata_t结构数组,大小根据CPU数量决定,每个schdata_t 结构,包含一个进程优先级大小的thrdlst_t 结构数组,挂载进程;

管理进程初始化:

init_krlsched 函数:初始化schedclass_t 结构实例,调用schedclass_t_init 函数,逐级初始化上述 的三个结构数组;

init_krlsched 函数被内核功能层的入口函数init_krl 函数调用;

2、实现进程调度器:

停止运行当前进程,让CPU开始执行另一个进程;

进程调度器入口:

krlschedul接口函数:调用krlsched_retn_currthread 函数返回当前运行进程,接着调用 krlsched_select_thread 函数选择下一个运行的进程;最后调用save_to_new_context 函数从当前进程切换到下一个进程;

获取当前运行进程:

krlsched_retn_currthread 函数 ,先得到是哪个CPU的cpuid,借此通过获取数据结构中sda_currtd 成员得到当前运行的进程;

选择下一个进程:

这是进程调度算法的核心:关乎进程的吞吐量、能否及时响应请求、CPU的利用率、各个进程之间运行获取资源的公平性;

cosmos系统选择简单的一个调度算法:优先级高的作为下一个进程;

krlsched_select_thread 函数:从最高优先级开始扫描,若当前优先级的 链表不为空,取出该链表下的第一个进程,执行脱链,旧的当前进程先挂入链表尾,再将新的当前进程挂入tdl_curruntd 字段;

若扫描到最后,也没有找到进程,就返回默认的空转进程;

获取空转进程:

空转进程的必要性:调度器的功能必须是从一个切换到另一个进程,若没有下一个进程,且上一进程又不能运行,系统将停止运行;

krlsched_retn_idlethread 函数,与获取当前进程函数设计一样,只不过获取的schdata_t 结构中的sda_cpuidle 空转进程;

进程切换

进程在内核中的函数调用路径:通俗讲就是一个进程中的函数层层调用,直到调用进程调度器函数,中间的调用函数顺序就是函数调用路径;通过栈保存;

save_to_new_context 进程切换函数:首先保存当前进程的通用寄存器到当前进程的内核栈中;

然后 保存CPU的RSP寄存器 到当前进程的机器上下文中,并且读取 保存在下一个进程机器上下文的RSP的值,把它存到CPU的RSP寄存器中;

接着 调用函数切换MMU页表;

最后从下一个进程的内核栈中恢复下一个进程的通用寄存器;

通过切换进程的内核栈,切换进程,因为进程的函数调用路径就保存在对应的内核栈中,只要调用 krlschedul 进程调度函数,最后的函数调用路径一定会停在 save_to_new_context 函数中,当 save_to_new_context 函数一返回,就会导致回到调用 save_to_new_context 函数的下一行代码开始运行,在这里就是返回到 krlschedul 函数中,最后层层返回;

这个机制的前提是:下一个进程已经被调度过,执行过krlschedul函数;

对于新建进程,没有调用过krlschedul 函数,需要特殊处理;

__to_new_context 函数:负责设置当前运行的进程,处理CPU发生中断时需要切换栈的问题,又切换一个进程的MMU页表;如果是新建进程第一次运行,就调用retnfrom_first_sched 函数进行处理;

该函数不会返回到调用它的__to_new_context 函数,直接运行新建进程的代码;

关键词: