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

目录

  • 第一关 版本1.2内核的进程调度过程分析
    • (一)答案
      • 1.`mygdb`侧调试命令:
      • 2.`第三关.txt`:
    • (二)解题思路
      • 1.概述:0号进程和1号进程间进程调度过程
        • (1)从`system_call`函数进入相应的系统调用函数
        • (2)执行`sys_alarm`和`sys_pause`系统调用函数
        • (3)进程调度与函数调度的关系
      • 2.从第二次输出1的开始到第三次输出1之前,进程调度与函数调用关系示意图
  • 第二关:~~两个进程的 严格交替输出~~ (从第一次循环开始两个进程严格交替输出)
    • (一)答案
    • (二)思路
      • 1.分析原`schedule`函数导致`0`、`1`不严格交替输出的原因
      • 2.设计新`schedule`函数

第一关 版本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函数。
操作系统实验3.3 版本1.2内核的进程调度过程分析 && 两个进程的严格交替输出_第1张图片

(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:
操作系统实验3.3 版本1.2内核的进程调度过程分析 && 两个进程的严格交替输出_第2张图片

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

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

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

(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号进程的状态,重复上述操作。

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

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

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

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

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

(一)答案

1.2/linux/kernel/sched.c文件中的schedule函数添加如下图圈内内容。
操作系统实验3.3 版本1.2内核的进程调度过程分析 && 两个进程的严格交替输出_第9张图片

虽然最后结果里的前几个0/1没有严格交替输出,但是评测通过。
操作系统实验3.3 版本1.2内核的进程调度过程分析 && 两个进程的严格交替输出_第10张图片

(二)思路

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函数。

你可能感兴趣的:(操作系统课程实验,linux)