操作系统实验3.3 版本1.2内核的进程调度过程分析 && 两个进程的严格交替输出

第一关 版本1.2内核的进程调度过程分析

(一)答案

1.mygdb侧调试命令:

b task1
c
c
b schedule
c
disas 0x6973
p sys_call_table[0x1b]
c
disas 0x69ae
p sys_call_table[0x1d]
c
c
c
c
c

2.第三关.txt:

在这里插入图片描述

(二)解题思路

1.概述:0号进程和1号进程间进程调度过程

(1)从system_call函数进入相应的系统调用函数

在两个进程运行alarmpause函数时,到执行alarmpause系统调用时,都会进入到system_call函数,在下图第一处划线位置根据系统调用号,调用相应的sys_alarmsys_pause函数。
在这里插入图片描述

(2)执行sys_alarmsys_pause系统调用函数

两个函数的共同点在于都是系统调用的函数,因此在执行这两个函数之前会进入上面说的system_call函数,在执行完上一一张图提到的划线部分的call sys_call_table指令后,也均会执行reschedule(除了第一次的system_call(alarm),但这次例外出现在题目中要求的 “第二次输出1” 之前,因此本文不做考虑(水平有限,没想明白)),reschedule会调用一次schedule函数。
而不同点在于,sys_alarm函数本身内部并没有调用schedule函数,而sys_pause函数内部调用了一次schedule函数,因此在main函数调用alarm系统调用时,alarm系统调用共执行了一次schedule,而main函数的1号进程和0号进程调用pause系统调用时,pause系统调用共执行了两次schedule

sys_alarm:
请添加图片描述

sys_pause
在这里插入图片描述

reschedule
在这里插入图片描述

main
请添加图片描述

(3)进程调度与函数调度的关系

在执行schedule函数时,会发生进程的调度,在第一关中,每一次的进程调度都会导致0号进程与1号进程间的切换,由于进程在切换时,老进程会保留当前退出内存时的状态,,比如从0号进程执行到main函数for循环中,task0函数下一行的pause函数,这时pause系统调用会进入system_call函数,通过下图划线位置的call sys_call_tablepause的系统调用号调用sys_pause函数,执行到sys_call函数的schedule时,先保存这时的0号进程的执行状态,再切换到1号进程,下次从1号进程再切换到0号进程时,保存的0号进程的状态会使得0号进程从call schedule的下一条指令(大概是这个意思,可能不准确)开始执行,随后,一次退出sys_pausesys_call_table,回到system_call函数,直至执行到call reschedule中的schedule函数,再保存0号进程的状态,重复上述操作。

在这里插入图片描述

2.从第二次输出1的开始到第三次输出1之前,进程调度与函数调用关系示意图

请添加图片描述

请添加图片描述

第二关:两个进程的 严格交替输出 (从第一次循环开始两个进程严格交替输出)

(一)答案

1.2/linux/kernel/sched.c文件中的schedule函数添加如下图圈内内容。
在这里插入图片描述

虽然最后结果里的前几个0/1没有严格交替输出,但是评测通过。
在这里插入图片描述

(二)思路

1.分析原schedule函数导致01不严格交替输出的原因

在上一关中的思路中提到:
alarm系统调用共执行了一次schedule,而main函数的1号进程和0号进程调用pause系统调用时,pause系统调用共执行了两次schedule
所以一次for循环中,打印一个00号进程一共要调用两次schedule函数(pause的两次),而1号进程要调用三次schedule函数(pause的两次和alarm的一次),正是这样不为1:1schedule的调用次数比(即进程调度、切换的次数,因为原schedule函数使得只要该函数被调用,就会进行进程的切换),导致了从输出第二个1开始的10100这样的输出循环中,01并非严格交替输出,且输出的0输出的1 = 3:2(这是因为1号进程调用了三次0号进程。而0号进程调用了两次1号进程)。

2.设计新schedule函数

那么只要使得1号进程中与0号进程中通过调度切换进程的次数为1:1即可解决该问题,而思路就是使得1号进程中的alarm函数在调用schedule函数的时候不进行进程的调度(切换)。
再看原schedule函数,其基本逻辑为:如果当前进程为0号进程,就让下一个进程为1号进程,如果当前进程为1号进程,就让下一个进程为0号进程。
需要将其逻辑改为:如果当前进程为0号进程,就让下一个进程为1号进程,如果当前进程为1号进程,且当前schedule函数,不是alarm函数调用的system_call中的reschedule调用schedule函数,就让下一个进程为0号进程,否则下一个进程依然为1号进程
如何判断上述思路中当前schedule函数是否为alarm函数调用的system_call中的reschedule调用的schedule函数:
schedule函数中的task[next]->counter = 15;语句之前添加printk调试信息如下:

printk("Current pid = %d", current->pid);
printk("Current alarm = %d", current->alarm);

(为什么打印current->alarm:因为在调用alarm函数中的sys_alarm中修改了alarm的值,判断current->alarm为区别alarmpause的特征参数。)
发现0号进程的current->alarm的值总为01号进程的current->alarm的值一直为正值且在增加,于是构造答案所示的schedule函数。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值