OS21.【Linux】进程状态(2) O(1)调度算法、进程切换和其他概念

目录

1.知识回顾

2.Linux内核的 O(1)调度算法

前置知识

位图

运行队列

O(1)调度算法

3.竞争性、独立性、并行、并发的概念

4.进程切换的步骤

解释进程的上下文

结论

进程的上下文保存的位置

拓展阅读


1.知识回顾

参考以下文章复习;

OS19.【Linux】进程状态(1)

OS20.【Linux】进程状态(2) 僵尸进程、孤儿进程和进程优先级

2.Linux内核的 O(1)调度算法

前置知识

位图

参见CC55.【C++ Cont】位运算的最终总结(含比特位计数、汉明距离)文章

运行队列

参见OS19.【Linux】进程状态(1)文章

O(1)调度算法

运行队列runqueue中有两个指针数组:running和waiting:running指向运行队列指针数组,waiting指向过期队列指针数组,指针数组的每一个元素又指向一个数组

struct runqueue
{
    struct task_struct* running[140];
    struct task_struct* waiting[140];
    //......
}

下标从0到99一般不用,只用下标从100到139-->恰好40个

之前在OS20.【Linux】进程状态(2) 僵尸进程、孤儿进程和进程优先级文章提到过nice的取值范围是[-20,19],一共40个级别,恰好和100到99的个数一样

分别映射两张表,利用优先级对进程排队:

1.40个元素是40个指针,指向40个队列

2.对于指针数组中下标为i的元素,其NI值为i-120,PRI值为PRI(old)+(i-120)

   例如running[i]指向PRI值为PRI(old)+(i-120)的进程的运行队列

3.CPU会根据进程的优先级的大小,来执行running中对应优先级的队列

CPU想执行优先级为PRI的进程们,会获取running中指向优先级为PRI的运行队列的元素

4.当时间片到了,如果进程没有被CPU调度完,会将该进程放入过期队列(waiting[i]指向的数组)中,等待下一次调度

5.这两个队列(running和waiting指针数组)是镜像关系,新来了的进程加到过期队列中,不影响运行队列(注意新来了的进程不能加到运行队列中,否则如果出现优先级比它大的进程,优先级小的进程会一直得不到执行)

进一步解释:

1.如何判断running中所有元素指向的运行队列中的进程全部被调度完?

Linux内核中有一个 nr_active 变量,CPU会看nr_active的值是否为0,不为 0继续调度,为0则进行过交换两个指向两个指针数组(running和waiting)的指针

2.如何查找运行队列中优先级最高的且处于队头的进程?

传统的判断方法:遍历数组,时间复杂度太高

新的判断方法:位图

定义一个char bitmap[5],char为8位,那么一共5*8=40位,刚好对应NI(nice值)的所有取值

操作系统只需要分析每一位(一共40位),如果为0,表示对应优先级的进程被执行完了,如果为1,表示对应优先级的进程没有被执行完了

从最低位(优先级最低进程是否存在)到最高位(优先级最高进程是否存在),一共40位,可以使用各种位运算的方法查找最右边的"1". 通过1的位置来计算出所有进程的最高优先级(因为bitmap越往右下标越大,对应进程的优先级越高),转到该优先级的运行队列中去调度进程,这样调度的时间复杂度为O(1)

// 扫描 bitmap 位图,查看哪一个区间有活跃进程,快速定位,并调度
for(int i = 0; i < 5; ++i)
{
    if(bitmap[i] == 0) // 表明当前组内没有活跃进程
    {
        continue;
    }
    else
    {
        // 表明当前组内有活跃进程,并从32个比特位确定活跃进程在哪一个队列中
        // 位运算操作取出最右边的1
    }
}

6.running所有元素指向的运行队列中的进程全部被调度完,那么交换两个指向两个指针数组(running和waiting)的指针,让运行队列变成过期队列, 过期队列变成运行队列,这样CPU能继续调度了

3.竞争性、独立性、并行、并发的概念

1.竞争性: 操作系统上进程数目众多,而CPU资源是优先的,所以进程之间必定存在竞争

2.独立性: 多进程的运行期间互不干扰,它们各自独享各种资源(一个进程出现问题不会影响其他进程的运行)

3.并行: 多个进程在多个CPU下分别同时运行

4.并发:多个进程在一个CPU下采用进程切换的方式,在一段时间(通常很短)之内,让多个进程都得以推进(注:但从某个时刻来看,只有一个进程在运行)

由于CPU的运行进程的速度极快,所以用户会感觉进程都是在同时运行

4.进程切换的步骤

回顾OS19.【Linux】进程状态(1)文章的知识点:

从基于基于时间片的轮转调度算法来看,需要保证所有进程公平地被调度,因此当一个进程的时间片到了,CPU会暂停执行该进程,转而执行下一个进程,这叫进程切换(process switch)

注:进程切换主要做的是上下文切换(进程切换还涉及到把进程放到过期队列里面),某些操作系统书籍会将进程切换(process switch)称为上下文切换(context switch)

那么进程切换的步骤是什么?

大致的步骤是这个:保存当前进程的上下文(context)→更新进程状态→选择下一个要运行的进程→恢复新进程的上下文→CPU去调度新进程

(摘自Computer Systems A Programmers Perspective书,演示进程切换) 

解释进程的上下文

当一个进程没有执行完时,但该进程的时间片到了,而CPU在执行新的进程之前需要保存旧进程的上下文

保存旧进程的上下文肯定要保存CPU执行到进程的第几行代码了,需要获取CPU最后执行代码的下一行代码的地址,可以从程序计数器PC中获取

之前在OS17.【Linux】进程基础知识(1)文章提到过程序计数器PC的含义:

寄存器层面上为16位下为CS:IP,x86架构下的EIP寄存器,x64架构下的RIP寄存器

这里以32位为例:进程的上下文包括EIP寄存器的值

只保存EIP寄存器的值是不行的,还需要保存其他寄存器,例如栈帧(复习可参见36.【C语言】函数栈帧的创建和销毁文章)还和EBP、ESP 寄存器有关

CPU中的寄存器保存的是进程的临时数据(进程的上下文的一部分)

!!!进程上下文不止含各个寄存器的值,还有其他东西:

摘自:https://tldp.org/LDP/LG/issue23/flower/context.html

The context of a process includes its address space, stack space, virtual address space, register set image (e.g. Program Counter (PC), Stack Pointer (SP), Instruction Register (IR), Program Status Word (PSW 程序状态字) and other general processor registers), updating profiling or accounting information, making a snapshot image of its associated kernel data structures and updating the current state of the process (waiting, ready, etc). 

结论

1.老进程的时间片到了,如果不保存老进程的上下文,当新进程运行时,CPU中老进程的数据会被覆盖,导致老进程的数据丢失. 因此进程从CPU上离开时,必须保存上下文数据

2.保存的目的未来都是恢复: 当老进程被唤醒时能从之前的数据继续运行,即恢复上下文

进程的上下文保存的位置

软件级别进程的切换,进程的上下文保存在PCB中

硬件级别进程的切换,进程的上下文保存在任务状态段TSS(Task-State Segment)中

32位的TSS,里面包含各个寄存器值的分布位置,下图中所标注的偏移量是十进制的:

(摘自Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3A: System Programming Guide, Part 1) 

CPU用任务寄存器TR任务寄存器(Task Register)来指向当前任务的TSS,当进程切换发生的时候,寄存器TR的内容也会跟着指向新进程的TSS

处理器固件能够识别TSS 中的每个元素,并在任务切换的时候读取其中的信息

拓展阅读

1.https://tldp.org/LDP/LG/issue23/flower/context.html

离线观看的htm文件分享链接:

Processes and Process Context.htm
https://pan.baidu.com/s/1yaKULZIHQ4h-dgcdy-Ckxw?pwd=mten 提取码: mten

2.https://www.sanfoundry.com/process-in-operating-system/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zhangcoder

赠人玫瑰手有余香,感谢支持~

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

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

打赏作者

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

抵扣说明:

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

余额充值