《linux内核分析》第二次课 实验作业

潘聪  原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

这次的实验主要是研究线程调度中的主动调度。

---------------------------------------------

一、基础结构

(1)进程:在mypcb.h中,进程由ip(eip)和sp(esp)共同组成。

(2)进程控制块(PCB):进程号pid,状态(错误/运行中/停止运行),进程堆栈(包括内核栈和用户栈,此处合二为一了,详见[1]),进程,任务入口,通过next指针组成一个链表。

二、初始化(__init my_start_kernel)

生成零号进程:进程号0,状态运行,任务入口和ip为my_process的地址(此处将函数名作为指针使用,返回函数地址),sp设置为栈顶,链表next指向自身。

生成其他进程:进程号依次分配,入口与零号进程相同,状态为未运行,sp设置为各自的栈顶(每个进程维护一个自身的栈),使链表连成环状链表。

当前任务设定为零号进程。

asm代码段:

 1     asm volatile
 2     (
 3         "movl %1, %%esp
	" //set task[pid].thread.sp to esp
 4         "pushl %1
	" //push ebp
 5         "pushl %0
	" //push task[pid].thread.ip
 6         "ret
	" //pop task[pid].thread.ip to eip
 7         "popl %%ebp
	"
 8         :
 9         : "c" (task[pid].thread.ip), "d" (task[pid].thread.sp)
10     );

将零号进程的栈顶指针esp赋值给系统的esp,并将esp压栈(可以理解为ebp压栈),并将零号进程的ip压栈,并使用ret指令从该ip开始执行指令。

理论上,如果这些进程不退出的话,最后一行popl永远不会被执行。

三、主进程方法(my_process)

每个指令周期进行一次循环,每10000000此循环后打印当前运行进程的进程号两次;若进程调度标识为1,在两次打印期间执行调度函数。

四、调度句柄(my_timer_handler)

每次中断后开始运行该函数,累积1000次中断后将调度标识置为1,从而使主进程方法运行调度函数。

五、调度函数(my_schedule)

定义两个tPCB类型的指针,分别指向当前进程和下一个进程。针对下个进程的运行状态不同(运行中或其他)分为两段汇编代码进行对应的进程上下文切换。

1)下个进程正在执行:

 1 asm volatile
 2                 (
 3                         "pushl %%ebp
	" //save ebp
 4                         "movl %%esp, %0
	" //save esp
 5                         "movl %2, %%esp
	" //restore esp
 6                         "movl $1f, %1
	" // save eip |1f mean label 1
 7                         "pushl %3
	"
 8                         "ret
	" //restore eip
 9                         "1:	" //next process start here
10                         "popl %%ebp
	"
11                         : "=m" (prev->thread.sp), "=m" (prev->thread.ip)
12                         : "m"(next->thread.sp), "m" (next->thread.ip)
13                 );

将ebp压栈,当前进程的sp记录esp,当前进程的ip记录label1的地址,当进程切换返回后将栈中原ebp的内容重新弹回到ebp中。

除此之外,还将当前进程设为下一进程,并打印切换文字。

2)下个进程未执行:

在执行汇编命令之前,先将下一进程状态设置为运行中,并将其设为当前进程。

执行的汇编代码与1)类似,在此不进行赘述。

 ------------------------------------------------------------------------------

最后,make后使用命令qemu -kernel arch/x86/boot/bzImage,生成图见下图:

--------------------------------------------

[1]从迷你型linux内核理解进度调度的原理http://itdreamerchen.com/%E4%BB%8E%E8%BF%B7%E4%BD%A0%E5%9E%8Blinux%E5%86%85%E6%A0%B8%E7%90%86%E8%A7%A3%E8%BF%9B%E7%A8%8B%E8%B0%83%E5%BA%A6%E7%9A%84%E5%8E%9F%E7%90%86/ 

原文地址:https://www.cnblogs.com/codingpenguin/p/4340590.html